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'
        ))" }
posh-git Release v0.1