Question:
Is there a better approach for passing information into script blocks in where-object
filter scripts than using parent-scoped variables?
Background:
I have a script that looks for un-checked-in and/or modified source files vs. source control and has a parameter that allows it to do a more exhaustive search. I use where-object
in a couple of places with a script block object contained in a script-scoped variable that I customize based on the input parameters to the script.
So, if you ask for a thorough search, the filter will compare the candidate file against all TFS files to see if the file isn’t in source control, if you choose the less-thorough search, the filter will only compare against checked-out files to see if the file is modified but not checked out.
The customized script blocks refer to script-scoped variables containing the results of doing queries against source control.
So my problem is that I’d like to get rid of a global (script-level) variable and pass all the necessary information into the script blocks as parameters to the script blocks. If I was using invoke-command
, I’d use the ArgumentList
parameter to do this. Where-Object
doesn’t seem to have that. One downside of using parent-scoped variable references in the script blocks is that I can’t change those variables, so I can’t do lazy initialization (or at least I haven’t figured out how yet, not being an expert on the scoping rules for Powershell.)
Answer:
Just to expand a bit on what Keith mentioned, you could do it like this:
1 2 3 4 |
ps> $x=2 ps> 1..5 | where (& {param($v); { $_ -eq $v }.getnewclosure() } $x ) 2 |
I tried closing over implict $args
to save the param declaration but $args
seems exempt from capture. More likely it is being captured but just getting stomped on.
$x
could easily be replaced with another function call like (get-x)
.
Essentially I’m calling a scriptblock that returns a scriptblock which closes over the outer scriptblocks parameter. Same implementation as Keiths essentially, just a little more succint [and obtuse.] Lambdas for the win.
I only wish there was a more pithy way to get closure semantics. That said, I’m glad the method got put in rather than not.
-Oisin