PowerShell Live - being retired

Please go to http://www.shelltools.net for more information

Welcome to PowerShell Live - being retired Sign in | Join | Help
in
Home Main Site Blogs Forums Videos Chat Customer Support

Karl Prosser on Powershell

Powershell Refactored. – Introduction and Invoke Ternary.

Powershell Refactored. – Introduction and Invoke Ternary.

 

The purpose of this column is to present powershell filters, functions and cmdlets. I have always wanted to make my own language, and in the past have experimented with and made some, mostly domain specific, however the effort to make a general purpose language as good as the ones I used in my day to day professional was too much, so they were mostly eccentric hobby projects for the sake of learning.

 

One thing I love about powershell is just how easily it can be extended. With carefully designed and thought out functions, cmdlets and filters you can make powershell look and feel about just like anything. In fact certain build in cmdlets that you use everyday, like foreach-object, where-object, compare-object, sort-object, measure-object and select-object, aren’t really part of the powershell language so much as they have anything to do with the built in keywords or powershell engine, but they are only part of the powershell language because they were shipped with it, However internally these cmdlets are very simple, but they are well thought out functions, and very useful, and practically are part of the language.

 

The goal of this column is to produce and share functions that are just as useful and generic as those built in ones, and extend powershell in areas where it is lacking. When extending a language like this, we have to be careful, that the extensions follow a consistent look, feel, and behavior. Also we want to make sure the extensions are very generic, in that they can be used in just about any context, and finally we don’t want to dilute the language. So we have to make very useful and powerful functions, that are easily understandable , and don’t balloon into too many keywords that would confuse users.

 

So this weeks’s “powershell refactored function” is invoke-ternary, a function I had released some time ago, and is included as part of PSCX (Powershell Community Extentions). Jeffery snover blogged about this function here. One of the glaring omissions in powershell is a ternary operator. A ternary operator is valuable in any programming language, but neccisary even more in powershell , since more often that not in powershell, commands aren’t executed over a number of lines, but through embedded expressions inside scriptblocks at various stages of the pipeline. i.e

 

"F","M","M","F" | foreach-Object { "its a $_" }

 

Expressions So often I found that I was unneccisarily writing embedded if statements inside these scriptblocks as below:

 

"F","M","M","F" | foreach-Object { if ($_ -eq "M") { $a = "boy"} else {$a = "girl"}; "its a $a" }

 

E Which made things harder to read, and didn’t give me the speed/pithyness typical of powershell, and got messy in more complex scenarios. The need for a ternary operator was just screaming out at me. So since the normal pattern for ternary operations in most C based languages is  <true/false expression> ? <true value> : <false value> I wanted to use ? and :, so I chose to call the function ?: but really that is better as an alias so I called the function Invoke-ternary and made an alias called ?:

Here is that function

 

set-alias ?: Invoke-Ternary -Option AllScope -Description "PSCX filter alias"

filter Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse)

{

   if (&$decider) {

      &$ifTrue

   } else {

      &$ifFalse

   }

}

 

The scope of this column isn’t’ to get into how it works, but you can see its not many lines  of code. This attests really to the awesome design of powershell. So how would we do our previous example.

 

"F","M","M","F" | ?: {$_ -eq "M"} {"its a boy"} {"its a girl"}

 

Here you can see  that the decider, and the true and false sections have to be scriptblocks, and also note that it is a filter, and this works on the pipeline directly, allowing us not to have to embed this in a foreach-object.  So you could do something like:

 

"F","M","M","F" | ?: {$_ -eq "M"} "its a boy" "its a girl"

 

A great this about the community is that people can pick up on things and improve it.  

 

The above function was hashed out really quick. Nick Howell noticed that though it is powerful to allow the decider, and the true and false expressions to be scriptblocks so they can contain a lot of logic, but often you are just returning static objects.

. that is also the case in the examples before.. So it would be nice to not have to have “it’s a boy” inside a scriptblock, as in this case it is redundant, so he improved the function. So that you could do something like this:

 

"F","M","M","F" | ?: {$_ -eq "M"} "its a boy" "its a girl"

 

Unfortunately there were some issues with nicks version and it didn’t work in many situations, but it was a good idea. In a later column I will introduce a cmdlet version of this, which is more robust, designed for use in and outside the context of the pipeline, and it takes advantages of Cmdlets ability to have multiple parametersets.

 

That’s all for now.

 

Check out our join-object set of functions next week.

Published Friday, April 20, 2007 12:23 AM by karl

Comments

No Comments
Anonymous comments are disabled

About karl

I am one of the original creators of Powershell Analyzer, and the cofounder of Powershell Live.