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