是否有短路'或'返回第一个'真实'值?

时间:2014-02-23 22:34:49

标签: powershell short-circuiting

Scheme有一个短路or,它将返回第一个非假值:

> (or 10 20 30)
10
> (or #f 20 30)
20
> (or #f)
#f

在需要之前,它不会评估其参数。

PowerShell中是否有这样的内容?

以下是它的近似值:

function or ()
{
    foreach ($arg in $args) {
        $val = & $arg; if ($val) { $val; break }
    }
}

示例:

PS C:\> or { 10 } { 20 } { 30 }
10

示例:

PS C:\> $abc = $null

PS C:\> or { $abc } { 123 }
123

PS C:\> $abc = 456

PS C:\> or { $abc } { 123 }
456

4 个答案:

答案 0 :(得分:6)

你可以这样做:

10, $false, 20 | ? { $_ -ne $false } | select -First 1

结果是输入列表中的第一个值不是$false$null。由于$null是PowerShell treats as $false在比较中的值,因此上述内容应该符合您的要求。

答案 1 :(得分:3)

您正试图让PowerShell通过您的函数使用类似Scheme的语法。不要这样做。编写惯用的PowerShell。试图强迫一种语言看起来像另一种语言只会让自己变得更加困难,为错误引入很多的空间,并且会混淆%$ ^%& ^ *(无论是谁需要维护你离开后的代码。

PowerShell似乎确实发生了短路。将此代码放在ISE中并在每个函数的write-output行上设置断点,然后启动调试器(F5):

function first () {
    write-output "first"
}

function second() {
    write-output "second"
}

$true -or $(first) -or $(second);
$false -or $(first) -or $(second);
$false -or $(second) -or $(first);   

$true计算结果为true(显然),因此它不会尝试处理超出该点的表达式。当倒数第二行处理时,只有first中的断点处理。当最后一行处理时,只有second()中的断点被击中。

答案 2 :(得分:2)

据我所知,内置的内容并不多。我认为你的功能看起来很不错。

使它成为流水线输入可能更惯用:

function or
{
    foreach ($x in $input) {
        $val = & $x; if ($val) { $val; break }
    }
}

示例:

PS > $abc = $null
PS > { $abc },{ 123 } | or
123    
PS > $abc = 456
PS > { $abc },{ 123 } | or
456

答案 3 :(得分:1)

只要你给这个函数一个好名字,我认为创建这样一个函数是完全惯用的Powershell。我要对OP的实现做一个调整就是在脚本块中传递可选:

function Select-FirstValue {
    $args |
        foreach { if ($_ -is [scriptblock]) { & $_ } else { $_ } } |
        where { $_ } |
        select -First 1
}

然后调用者只需在可能产生副作用或性能代价高昂的参数周围添加{ }括号。

我正在使用这样的函数作为从配置文件中为param s提供默认值的简单方法。它看起来像:

function Do-Something {
    param([string]$Arg1)

    $Arg1 = Select-FirstValue $Arg1 { Get-ConfigValue 'arg1' } 'default arg1 val'

    [...]
}

这样,只有在用户没有传入参数时,才会尝试读取配置文件。