Powershell equivalent to F# Seq.forall
I've written this (which works):
function ForAll {
BEGIN {
$allTrue = $true
}
PROCESS {
if ($_ -lt 1) { $allTrue = $false }
}
END {
$allTrue
}
}
$aList = (0..4)
$bList = (1..4)
$aList | ForAll # 开发者_JS百科returns false
$bList | ForAll # returns true
But what I want to do is replace the ($_ -lt 1) with a function called something like $predicate that I pass into the ForAll function. I can't seem to get this to work. Any ideas?
Use [scriptblock], imho it is much easier than using functions here. That's the task why scriptblocks were invented.
function ForAll([scriptblock]$predicate) {
BEGIN {
$allTrue = $true
}
PROCESS {
if (!(& $predicate $_)) { $allTrue = $false }
}
END {
$allTrue
}
}
$aList = (0..4)
$bList = (1..4)
$aList | ForAll {$args[0] -le -10 } # returns false
$bList | ForAll {$args[0] -le 10 } # returns true
$args[0] denotes the first argument passed to the scriptblock - in this case it is $_.
If you're on PowerShell 2.0, you can use param with a scriptblock to declare parameters e.g.:
function ForAll {
param(
[Parameter(Position=0,Mandatory=$true)]
[scriptblock]
$Expression,
[Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true)]
[psobject]
$InputObject
)
Begin { $allTrue = $true }
Process {
foreach ($obj in $InputObject) {
if (!(&$Expression $obj)) { $allTrue = $false }
}
}
End { $allTrue }
}
$aList = (0..4)
$bList = (1..4)
ForAll {param($val) $val -gt 0} (0..4) # returns false
$aList | ForAll {param($val) $val -gt 0} # returns false
$bList | ForAll {param($val) $val -gt 0} # returns true
$aList | ForAll {param($val) $val -ge 0 -and $val -le 4} # returns true
For efficient processing we would use a filter instead of a function and we would "break" as soon as we found the spurious element. This also stops all upstream process too:
filter ForAll([scriptblock] $predicate) {
PROCESS {
if ( @($_ | Where-Object $predicate).Length -eq 0 ) {
$false;
break;
}
}
END {
$true;
}
}
Use it idiomatically:
(0..4) | ForAll { $_ -gt 0 } # returns false
(1..4) | ForAll { $_ -gt 0 } # returns true
精彩评论