Lazy PowerShell Coalesce-Args
A while back I posted a coalesce function for PowerShell that would try to return the first non-null argument passed to it. One drawback of this function is that each argument expression will be evaluated before being passed into the function. This didn’t work so well for posh-git, where each call to git
adds undesirable delay to the prompt. To address this issue, I wrote a new ScriptBlock-aware version that allows us to defer execution of the fallback cases until we need them:
function Coalesce-Args {
$result = $null
foreach($arg in $args) {
if ($arg -is [ScriptBlock]) {
$result = & $arg
} else {
$result = $arg
}
if ($result) { break }
}
$result
}
Set-Alias ?? Coalesce-Args -Force
It’s worth pointing out that this is probably the first time I’ve actually used a foreach
statement in PowerShell, specifically for break
support. The vast majority of the time it’s preferred to use the pipeline and ForEach-Object
.
For an example of usage, here’s how posh-git tries to determine the current branch name in Get-GitBranch:
$b = ?? { git symbolic-ref HEAD 2>$null } `
{ "($(
Coalesce-Args `
{ git describe --exact-match HEAD 2>$null } `
{
$ref = Get-Content $gitDirHEAD 2>$null
if ($ref -and $ref.Length -ge 7) {
return $ref.Substring(0,7)+'...'
} else {
return $null
}
} `
'unknown'
))" }