Joel-On-Software on the power of a good language

Joel Spolsky of Joel-On-Software fame, just posted a blog, “Can Your Programming Language Do This?” http://www.joelonsoftware.com/items/2006/08/01.html

In this article, he drives home the point that when it comes to code: Maintainability, Readability, Abstraction == Good!  He then points out how languages can help or hinder this and goes on to articulate the things a language should do to help.  We couldn’t agree more.  He could have renamed the article, “Why Windows PowerShell is a Great Language!”. 

Open up Joel’s blog entry in a separate window and compare the code. You should notice 2 things immediately

  1. Windows PowerShell code looks amazingly like the code Joel said he wanted.  There are a couple of syntactic differences but not many.
  2. Windows PowerShell is giving you answers!  In other words, I did everything using the interactive console.

Joel uses the function ALERT to display info so to make it easier to compare, I created an Alias:

PS> Set-Alias Alert Write-Host

PS> Alert “I’d Lke some Spaghetti!”

I’d Lke some Spaghetti!
PS> Alert “I’d Lke some Chocolate Moose!”

I’d Lke some Chocolate Moose!

 

Noone likes repeated code so he created a function:

PS> function SwedishChef ($food)

>> {   Alert “I’d like some $food !”

>> }

>>

PS> SwedishChef Spaghetti

I’d like some Spaghetti !
PS> SwedishChef “Chocolate Moose”

I’d like some Chocolate Moose !

 

Joel then makes the point that being able to pass functions as parameters increases the chances that you’ll be able to find common code:

PS> Function PutInPot($Ingredient) {Alert “POT: $Ingredient added”}

PS> Function BoomBoom($Ingredient) {Alert “BOOM: $Ingredient”}

PS> Function Cook ($i1, $i2, $f)

>> {  Alert “Get the $i1″

>>    &$f $i1

>>    &$f $i2

>> }

>>

PS> Cook Lobster Water PutInPot

Get the Lobster
POT: Lobster added
POT: Water added
PS> Cook Chicken Coconut BoomBoom

Get the Chicken
BOOM: Chicken
BOOM: Coconut

 

He then points out that the problem with this is that you have to have the functions defined a priori.  Wouldn’t it be more flexible/powerful if you could write them inline instead of declaring them elsewhere (anonymous functions)?  If you could do that, then it reduces the cost/burden to reuse code:

PS> Cook Lobster Water {Param($x) Alert “Pot $x”}

Get the Lobster
Pot Lobster
Pot Water
PS> Cook Chicken Coconut {Param($x) Alert “Boom $x”}

Get the Chicken
Boom Chicken
Boom Coconut

 

Once you have anonyous functions as arguments, you begin to see the world in a different way.  First Joel shows you a traditional approach to doubling all the elements of an array:

PS> $a = 1,2,3

PS> for ($i = 0; $i -lt $a.length; $i++) {Alert $a[$i]}

2
4
6

But now let’s use write a generic function which takes a function and an array as parameter and then applies that function to each element in the array:

PS> function map ($fn, $a)

>> {  for ($i = 0; $i -lt $a.length; $i++)

>>    {  $a[$i] = &$fn $a[$i]

>>    }

>> }

That allows you to now do this:

PS> $a = 1,2,3

PS> map {param($x) return $x*2} $a

PS> map Alert $a

2
4
6

 

Another example of this is the following 2 functions.  Both of these add elements to an initial value.  In the first case (SUM), the elements are added as integers.  In the second case (JOIN), the elements are added as strings.

PS> function sum ($a)

>> {  $s = 0

>>    for ($i = 0; $i -lt $a.length; $i++)

>>    {   $s += $a[$i]

>>    }

>>    return $s

>> }

PS> function join ($a)

>> {  $s = “”

>>    for ($i = 0; $i -lt $a.length; $i++)

>>    {  $s += $a[$i]

>>    }

>>    return $s

>> }

>>

PS> alert (sum 1,2,3)

6
PS> alert (join “a”,”b”,”c”)

abc

 

Look at the details of these functions and you’ll see that they are almost identical except for the initial value (0 vs “”).  So now let’s refactor these functions to use a common function (REDUCE):

PS> function reduce ($fn, $a, $init)

>> {  $s=$init

>>    for ($i = 0; $i -lt $a.length; $i++)

>>    {  $s = &$fn $s $a[$i]

>>    }

>>    return $s

>> }

PS> function sum ($a)

>> {  return reduce {param($a,$b) return $a + $b} $a 0

>> }

>>

PS> function join ($a)

>> {  return reduce {param($a,$b) return $a + $b} $a “”

>> }

>>

PS> alert (sum 1,2,3)

6
PS> alert (join “a”,”b”,”c”)

abc

Joel – thanks for an the eloquent articulation of the value of Windows PowerShell! 

Jeffrey Snover [MSFT]
Windows PowerShell/Aspen 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

 

PSMDTAG:FAQ: Anonymous Functions – are they supported? ANSWER: YES

PSMDTAG:LANGUAGE: Anonymous Functions