getnewclosure() VS [scriptblock]::create()

One of the cool new things that was added in Powershell V2 was the getnewclosure() method for scriptblocks. The Powershell Team blogs about it here.

This is the example they use:

function add([int]$x) { return { param([int]$y) return $y + $x }.GetNewClosure() }
$m2 = add 2
$m5 = add 5
&$m2 3 #expected: 5 actual: 5
&$m5 6 #expected: 11 actual: 11

And it works as advertised.

Not to sound like an unappreciative Luddite, but I have yet to see an implementation of this method that couldn’t also be solved using [scriptblock]::create().

[scriptblock]::create() basically constructs a new script block from a text argument. Because the text argument is being interpreted in the current scope, it doesn’t have any problem with scoping of the varibles being used. All the variable substitutions are done in the current scope during the creation of the script block. This also means that you can use $args, and don’t have to parameterize all the variables being used in the script block.

Here’s the same script, implemented using [scriptblock]::create()

function add([int]$x) {return [scriptblock]::create(‘return $args[0] + ‘ + “$x”)}
$m2 = add 2
$m5 = add 5
&$m2 3 #expected: 5 actual: 5
&$m5 6 #expected: 11 actual: 11

It produces the same results. The downside is having to do the string construction so that the proper variables references get expanded or expressed as literals.

It gets a little more interesting putting both to a performance test.

Here’s the test setup:

$count = 1..10000

“Using getnewclosure()”
(measure-command{
foreach ($i in $count){
function add([int]$x) { return { param([int]$y) return $y + $x }.GetNewClosure() }
$m2 = add 2
$m5 = add 5
&$m2 3 #expected: 5 actual: 5
&$m5 6 #expected: 11 actual: 11
}
}).totalseconds

“Using parameterized [scriptblock]::create()”

(measure-command{
foreach ($i in $count){

function add([int]$x) {return [scriptblock]::create(‘param([int]$y) return $y + ‘ + “$x”)}
$m2 = add 2
$m5 = add 5
&$m2 3 #expected: 5 actual: 5
&$m5 6 #expected: 11 actual: 11
}
}).totalseconds

“Using args[0] with [scriptblock]:create()”

(measure-command{
foreach ($i in $count){
function add([int]$x) {return [scriptblock]::create(‘return $args[0] + ‘ + “$x”)}
$m2 = add 2
$m5 = add 5
&$m2 3 #expected: 5 actual: 5
&$m5 6 #expected: 11 actual: 11
}
}).totalseconds

And the results:

Using getnewclosure()
18.8735097
Using parameterized [scriptblock]::create()
12.0665079
Using args[0] with [scriptblock]:create()
11.3925825

getnewcloser() is cool, but strangely, calling that method on an exsting script block takes longer than creating a new script block.

Advertisements

2 responses to “getnewclosure() VS [scriptblock]::create()

  1. Pingback: Tweets that mention getnewclosure() VS [scriptblock]::create() | The Powershell Workbench -- Topsy.com

  2. Thanks for posting,

    I am came across the .GetNewCloser method to other day, and just getting my head around it. I very much like your example too.

    I have recently started to learn/use PowerShell overt the last 3 months, have written some script to report on, managed and change windows and NetApp based systems.

    I am not sure where (apart from the command line) these two methods would be useful, i am sure they are very useful when required. To aid my learning, do you know of situations when these methods would be useful, i.e. when administering windows or AD or Exchange for example,

    Thanks again for posting
    Ernie

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s