Welcome to MSDN Blogs Sign in | Join | Help

DIY: Ternary operator

<Changed DYI => DIY.  jps>  

At Microsoft, "to ship is to choose".  One of the things we were very disappointed in not being able to ship in V1.0 is a ternary operator. Here is a description of a ternary operator from Wikipedia:

Many programming languages that use C-like syntax feature a ternary operator, ?:; unqualified, "ternary operator" usually refers to this. The ?: operator is used as a shorthand replacement for the if-then-else conditional statement; the general form is condition ? op1 : op2. If condition is true, the statement evaluates as op1; otherwise, it evaluates as op2.

Imagine the scenario where you give a discount of 10% all orders but 25% off those with a quanity greater than 10.  Without a ternary operator, you code it this way:

if ($quantity -le 10)
{   $total = ($quantity * $price) * .9
}else
{   $total = ($quantity * $price) * .75
}

If (when?) PowerShell supports ternary operators you will be able to do it this way:


$total = ($quantity * $price ) * ({$quantity -le 10} ? {.9} : {.75})

This would evalue the expression {$quantity -le 10} and if it is TRUE, it evaluates the first script block and uses that value {.9}, otherwise, it evaluates the second scriptblock and uses that value {.75}.

Did I mention that we didn't get around to supporting this in V1.0?  Well, the community comes to the rescue. 

In the PowerShell Community Extensions project over on CodePlex.com (which you can download/install from  http://www.codeplex.com/Wiki/View.aspx?ProjectName=PowerShellCX ), they have a ton of great stuff.  I installed this a while ago and am now getting around to investigating what is there (silly me - I should have done this on day 1).  Karl Prosser contributed a script called Invoke-Ternary and then defined an alias ?:  .  Using this does not provide the same syntax that you would get if/when the PowerShell parser supports this but it is pretty great. 

Here is the code:


# ---------------------------------------------------------------------------
# Name:   Invoke-Ternary
# Alias:  ?:
# Author: Karl Prosser
# Desc:   Similar to the C# ? : operator e.g.
#            _name = (value != null) ? String.Empty : value;
# Usage:  1..10 | ?: {$_ -gt 5} {"Greater than 5;$_} {"Not greater than 5";$_}
# ---------------------------------------------------------------------------
set-alias ?: Invoke-Ternary -Option AllScope -Description "PSCX filter alias"
filter Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse)
{
   if (&$decider) { 
      &$ifTrue
   } else { 
      &$ifFalse 
   }
}

This is a very tight, concise piece of code which is worthy of study.  What Karl is doing here is to leverage PowerShell's ability to treat code as a first class datatype [SCRIPTBLOCK] to CREATE HIS OWN CONTROL STRUCTURE!  He accepts 3 scriptblocks, he evaluates the first and if it is TRUE, he evaluates and returns the value of the second, otherwise it evalutes and returns the value of the third.  So going back to our original example, you can now code it this way (Notice the Syntax):


$total = ($quantity * $price ) * (?:  {$quantity -le 10} {.9} {.75})

Enjoy!

Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Published Friday, December 29, 2006 8:30 PM by PowerShellTeam
Filed under:

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# leedesmond&#8217;s blog &raquo; Blog Archive &raquo; Ternary operator ?:

Saturday, December 30, 2006 4:44 PM by leedesmond’s blog » Blog Archive » Ternary operator ?:

# re: DYI: Ternary operator

Made a few modifications for myself, and also added ?? (the coalescence operator):

<pre>

filter Invoke-Ternary ($Predicate, $Then, $Otherwise = $null)

{

  if($predicate -is [scriptblock]) { $predicate = &$predicate }

  if ($predicate) {

     if($then -is [ScriptBlock]) { &$then }

 else { $then }

  } elseif($otherwise) {

     if($otherwise -is [ScriptBlock]) { &$otherwise }

 else { $otherwise }

  }

}

filter Invoke-Coalescence($predicate, $alternative) {

if($predicate -is [scriptblock]) { $predicate = &$predicate }

Invoke-Ternary $predicate $predicate $alternative

}

set-alias ?: Invoke-Ternary -Option AllScope

set-alias ?? Invoke-Coalescence -Option AllScope

</pre>

Saturday, December 30, 2006 7:39 PM by Nick Howell

# re: DYI: Ternary operator

FYI thew equivalent of your Invoke-Coalescence is already in PSCX and is aliased to ?? e.g.:

$logdir = ?? {$env:logdir} {'C:\Temp'}

Again if PoSH supported this natively the syntax could be nicer:

$logdir = $env:logdir ?? 'c:\Temp'

Although we call the function rather lamely Inovke-NullAlt.  Mind if we steal this name for PSCX?  :-)  BTW, this is a nice equivalent of the KornShell "Foo = ${paramaeter:-word}" functionality.

Tuesday, January 02, 2007 3:28 AM by keith_hill

# re: DYI: Ternary operator

FYI DYI != DIY

ttfn

-mp

Thursday, January 04, 2007 5:13 PM by monkeypecker

# re: DIY: Ternary operator

Keith, feel free. If you want to be really picky, you might want to call it Invoke-NullCoalescence (which is probably the most accurate term for it).

I'm now considering something like this:

filter Invoke-NullCoalescenceMethod($Object, $Method, [array]$Parameters = @()) {

   ?: $Object {$item = $Object.PsObject.Members.Item($Method); if($item.Invoke) { $item.Invoke($Parameters) } elseif($item.get_Value -and $Parameters) { $item.Value = $Parameters } else { $item.Value }} $null;

}

Set-Alias ?. Invoke-NullCoalescenceMethod

It should work for getters, setters, and methods.

This is sortof like the null-drilldown offered in Cω (C-omega). It would be really super-fantastic if we could get some of these things in the language. I *really* like the idea of having this: $x?.StartInfo?.CreateNoWindow ?= $true;

That would just be handy.

Saturday, January 06, 2007 1:22 AM by Nick Howell

# Powershell Refactored. – Introduction and Invoke Ternary.

Powershell Refactored. – Introduction and Invoke Ternary. The purpose of this column is to present powershell

Friday, April 20, 2007 3:39 AM by Powershell Refactored

# Re: Ternary conditional operator

Check out Invoke-Ternary here [link] Shay [link]

Tuesday, September 18, 2007 9:52 AM by Latest Newsgroup Posts

# Powershell Refactored. – Introduction and Invoke Ternary.

Powershell Refactored. – Introduction and Invoke Ternary. The purpose of this column is to present powershell

Sunday, October 28, 2007 2:51 AM by Karl Prosser (MVP) on Powershell

Leave a Comment

(required) 
required 
(required) 
 
Page view tracker