Powershell: 建议:实现三元条件

创建于 2017-03-02  ·  52评论  ·  资料来源: PowerShell/PowerShell

C 风格的三元条件将是该语言的一个方便的补充。

例如,而不是写:

if ((get-date).tostring("ss") % 2) { 'odd'  } else  { 'even' }

可以写:

(get-date).tostring("ss") % 2   ?   'odd'   :    'even'

它还可以缓解长期以来的失望:

在微软,“交付就是选择”。 我们对无法在 V1.0 中发布感到非常失望的一件事是三元运算符。

来自 2006 年 12 月 29 日的PowerShell 团队博客文章


相关:实现空值合并和空值浸泡以及空值条件赋值

Committee-Reviewed Issue-Enhancement WG-Language

最有用的评论

@RichardSiddaway :如果我们在 PowerShell 标记的问题中查看 Stack Overflow _asked since 2014_,我们会得到(在撰写本文时):

  • 约 106,000 篇标记powershell帖子(这也包括答案;如果您将查询限制为问题,您会得到大约 46,000 个)
  • 其中,71个包含单词PSItem (其中13个是问题),即不到1%

$PSItem于 2012 年 9 月在 v3 中引入,因此为了安全起见,我选择 2014 作为查询的开始日期。

虽然这不是一个确切的指标,但不幸的是,该网站不允许您搜索$__ ,而且我确定有些问题包含 _neither_ $_$PSItem ,以及 v3 之前的问题仍在被问到 - 我仍然认为可以安全地得出$_的使用频率远高于$PSItem结论。

然而,更大的一点是没有必要_选择_:

正如$PSItem$_愉快地共存一样, ForEach-Object%Where-Object? ,.. .:

$a ? $b : $c可以与if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })共存

至于重述引入$a ? $b : $c的 _positive_ 原因

  • 使用大多数程序员熟悉的语法,更简洁,视觉上不那么混乱。

  • 更高效,因为不需要$(...)if语句需要它以允许它们作为更大表达式的一部分使用(它更嘈杂,效率更低,并且可能有意想不到的一面效果)

至于默默无闻的问题:

可以假设有人编写 _expressions_(而不是仅使用(简单)参数 _invoking commands_)具有一些开发人员经验,而我的(轶事)感觉是大多数开发人员至少 _recognize_ $a ? $b : $c作为缩写的if声明,无论他们是否积极使用它。

然而,即使他们不这样做,也很容易解释,除了使用不明显的 _symbols_ 之外,概念复杂性与if ($a) { $b } else { $c }的概念复杂性相同,甚至小于
$(if ($a) { $b } else { $c })

假设它一经介绍就流行起来——当然,这个讨论表明对它有需求——经常遇到它会使它成为一个熟悉且易于识别的习语(更简洁、更容易打字,至少对我和其他一些人来说)在这里,更具可读性) - 就像大多数人似乎更喜欢$_不是$PSItem

所有52条评论

请注意,随着允许从语句赋值的更改,对三元运算符的需求减少了。 你可以简单地做
$var = if ($x) { $x } else { $y }
它不像三元运算符那么简洁,但可以说更具可读性。

是的,但如果条件是更大表达式的一部分,您仍然必须使用$(...) _in additional_:

'The current sec. is ' + $(if ((get-date).tostring("ss") % 2) { 'odd'  } else  { 'even' })

对比

powershell 'The current sec. is ' + ((get-date).tostring("ss") % 2 ? 'odd' : 'even')

我知道可读性是……呃……读者的眼睛,但我个人觉得后者在视觉上更容易解析,而且少打字总是一个好处。

有了这样一个经常使用的功能,我认为记住更抽象的三元语法不会有问题(当然,人们可以继续使用if ,如果他们愿意的话)。

@mklement0我不得不同意以后的认知负担更小。

这绝对是我的首选。
@BrucePay ,是否有任何理由表明这是一个坏主意? 还是只是“发货就是选择”?

过去,这个功能请求被拒绝,因为经验不足的脚本编写者更难理解,并且 if 语句的表达形式更清晰,但更冗长。

我的个人观点:如果语言只适合我,我可能早就添加了。 但是……我发现许多开发人员不使用它,这实际上表明,经验不足的人在使用三元运算符时会遇到麻烦的假设是有道理的。

@lzybkr :

区分功能的_主动使用_与_识别_和理解它的能力是值得的。

显然,每个人都可以选择是否使用这样的功能,但是您是说“有麻烦”意味着经验不足的人在其他人的代码中看到它时不会_理解_它吗?

@mklement0 - 我们引入了$psitem作为$_的别名,因为有足够的反馈认为$_是神秘和令人困惑的,所以我相信三元运算符对于一些更少的人来说会很困难有经验的人来理解。

另一方面,PowerShell 中有许多元素让初学者甚至是经验丰富的开发人员感到困惑。

与任何其他语言一样,学习语言结构的语法和含义需要付出一些努力。
不知道是不是觉得三元运算符特别难掌握。

你有数据表明它是吗?

我相信唯一的数据是轶事,但批评适用于任何神秘的语言——bash、perl 等。

需要明确的是,我提供了历史背景。 也许 PowerShell 无处不在,因为更神秘的语法不会影响采用。

还要记住 - 一些简洁的语言仍然使用 if/then 作为三元运算符,例如 F#。

也就是说,也许可以使用更少的字符而不是太神秘:

if ($x) { $y } else { $z }
$x -then $y -else $z
$x ? $y : $z

-then/-else适合 PowerShell 语法 - 但是,一个运算符(或运算符,如果将其视为单个运算符太混乱的话),您可以获得不需要括号和大括号的好处。

再说一次,这会带来类似于foreachforeach-object麻烦。 但也许没有那么糟糕,我不知道。

@lzybkr :

顺势疗法剂量的隐秘是健康的:

值得称赞的是,PowerShell 总体上并不神秘,但在某些情况下,它提供了神秘的语法作为 _frequently used_ 构造的简洁 _alternative_(如果需要,您仍然可以详细),特别是?用于Where-Object%ForEach-Object

向我提供$x ? $y : $z作为if ($x) then { $y } else { $z }的简洁替代品是本着相同的精神。

?让人联想到_question_,因此暗示了一个条件(尽管在这种情况下是一个 _preceding_ ? ),并且——更重要的是——是 _a 来自几个潜在的熟悉结构其他语言_,具有相同的基本语义。

您无法通过$x -then $y -else $z获得同样的好处:它并不熟悉。

此外,虽然许多 PS 运算符确实有符号名称,但许多没有: * / + % ...
这些本质上也是神秘的,我们只是不再那样看待它们,因为它们是如此熟悉和无处不在。

我的感觉是$x ? $y : $z对很多人来说也已经很熟悉了,而且一旦引入到语言中,就会变得更加熟悉,因为经常需要简洁的条件。

请注意,您可以使用此运算符指定的内容非常有限。 特别是,除非将命令括在括号中,否则您将无法使用命令:

(test-path foo.txt) ? (get-content foo.txt) : (get-content bar.txt)

和....相比

if (test-path foo.txt) {get-content foo.txt} else {get-content bar.txt}

或者

get-content ((test-path foo.txt) ? "foo.txt" : "bar.txt")

对比

get-content $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"})

在我看来,在简洁性方面几乎没有优势,而在可读性方面则有明显的劣势。 当您拥有面向表达式的语言时,三元运算符就没那么有趣了。 当我 16 年前开始使用这门语言时,添加三元运算符似乎很明显来自 C 背景。 现在我很高兴我们从未添加它。 只是感觉像杂乱无章。

特别是,除非将命令括在括号中,否则您将无法使用命令:

这适用于 _any_ PowerShell 运算符。

并非所有 PowerShell 语句都涉及命令,当涉及命令时,用户已经知道(...)是命令的入场费(在大多数情况下)。

在你自己的例子中,对我来说((test-path foo.txt) ? "foo.txt" : "bar.txt")胜过$(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"}) ,因为需要$(...)的模糊性和花括号引入的噪音。

也许这只是我,但我发现这个:

get-content ((test-path foo.txt) ? "foo.txt" : "bar.txt")

比这更容易视觉扫描/解析:

get-content $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"})

我对这个问题唯一的抱怨是,如果你打算做三元?:那么你也应该做空合并??

$logDir = $env:LogDir ?? "$PSScriptRoot\Log"

我在野外看到了许多 Invoke-Ternary 和 Invoke-NullCoalescing 实现(例如 https://github.com/dahlbyk/posh-git/blob/master/src/Utils.ps1#L12)。 这表明人们普遍希望在语言中加入这样的功能。

@rkeithhill :我同意; re null-coalescing:已经存在一个问题,它也涵盖了 null-soaking:#3240

因此,经验不足的编码人员的论点将无法轻松使用空合并或三元代码语句,我认为这有点短视。 不需要使用这些“高级”功能,如果程序员因为缺乏经验而无法阅读代码,那么就我个人而言,这就是我需要快速学习新东西的提示。
当我第一次看到 C# 中的三元时,我觉得 WTF 是 MS 引入的这个新鲜地狱,直到我花了几分钟阅读了这个,然后我就被迷住了。

POSH 中的实际示例,我有这一行:
$mc_object = ($Message.fields | where Name -Match appname).Content
这很好而且很花哨,除非 $Message 对象没有名称为“应用程序名称”的归档属性,并且由于我无法控制来自 JSON 格式的数据,因此我必须确定要做什么。

因此,对于空合并操作,我所要做的就是在末尾添加?? ""以确保 $mc_object 始终是有效字符串,即使原始 setter 为空。 否则,我将不得不做一些不同的技术来完成 4 次击键可以做的事情,例如
$mc_object = if(-not ($Message.fields | where Name -Match appname).Content)){""}else{($Message.fields | where Name -Match appname).Content}
这对我来说是非常难以理解的,但是我可以通过做这样的事情来稍微清理一下,这就是我正在做的事情。
$mc_object = ($Message.fields | where Name -Match appname).Content if(-not $mc_object){$mc_object = ""}

虽然并不可怕,但要按下 4 个以上的键才能进行空凝聚。

无论如何,我绝对投票支持 Powershell 中的三元和 null-coelasce,它添加了一些非常高级的功能,并且只是使 Powershell 在任何系统的“核心”形式中使用时更具吸引力。

@lzybkr我还没有看到有人真正采用$PSItem 。 我在一个相当大的编写脚本的团队中工作,他们仍然使用$_ ,即使是经验不足的 PowerShell 用户。

@tibmeister或....

if (-not ($mc_object = $Message.fields.where{$_.Name -match 'appname'}.Content)) {
    $mc_object = ''
}

作为表达式的赋值会通过,但非常不可读。

我经常使用 $psitem

在多年的脚本游戏评判中,$psitem 在答案中被大量使用

@RichardSiddaway :如果我们在 PowerShell 标记的问题中查看 Stack Overflow _asked since 2014_,我们会得到(在撰写本文时):

  • 约 106,000 篇标记powershell帖子(这也包括答案;如果您将查询限制为问题,您会得到大约 46,000 个)
  • 其中,71个包含单词PSItem (其中13个是问题),即不到1%

$PSItem于 2012 年 9 月在 v3 中引入,因此为了安全起见,我选择 2014 作为查询的开始日期。

虽然这不是一个确切的指标,但不幸的是,该网站不允许您搜索$__ ,而且我确定有些问题包含 _neither_ $_$PSItem ,以及 v3 之前的问题仍在被问到 - 我仍然认为可以安全地得出$_的使用频率远高于$PSItem结论。

然而,更大的一点是没有必要_选择_:

正如$PSItem$_愉快地共存一样, ForEach-Object%Where-Object? ,.. .:

$a ? $b : $c可以与if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })共存

至于重述引入$a ? $b : $c的 _positive_ 原因

  • 使用大多数程序员熟悉的语法,更简洁,视觉上不那么混乱。

  • 更高效,因为不需要$(...)if语句需要它以允许它们作为更大表达式的一部分使用(它更嘈杂,效率更低,并且可能有意想不到的一面效果)

至于默默无闻的问题:

可以假设有人编写 _expressions_(而不是仅使用(简单)参数 _invoking commands_)具有一些开发人员经验,而我的(轶事)感觉是大多数开发人员至少 _recognize_ $a ? $b : $c作为缩写的if声明,无论他们是否积极使用它。

然而,即使他们不这样做,也很容易解释,除了使用不明显的 _symbols_ 之外,概念复杂性与if ($a) { $b } else { $c }的概念复杂性相同,甚至小于
$(if ($a) { $b } else { $c })

假设它一经介绍就流行起来——当然,这个讨论表明对它有需求——经常遇到它会使它成为一个熟悉且易于识别的习语(更简洁、更容易打字,至少对我和其他一些人来说)在这里,更具可读性) - 就像大多数人似乎更喜欢$_不是$PSItem

mklement0,你有一个非常棒的例子,我认为清楚地说明了这一点,谢谢。

重新阅读并重新审视并查看一些问题,我发现自己更倾向于建议的稍微冗长的语法:

$value = $a -eq $b -then $trueVal -else $falseval

或者,对于更语义可读的语法:

$value = $trueVal -if $a -eq $b -else $falseVal

@vexx32虽然我不介意你的第一个例子,但我发现表达式中间的条件非常重。

是的,我想我倾向于同意,但它确实读起来更......流畅。 但我还是倾向于第一个。

鉴于 PowerShell 旨在成为 C# 的“渐进式”语言,我认为使用? :是可行的方法。 甚至 JavaScript 也使用这种语法,它是当今最流行的语言之一。 :-)

同意, @rkeithhill ,因为熟悉其他几种语言的构造_和_希望也有空合并、空浸泡和空条件赋值,这些在 C# 中也基于?

后两种-如$foo?.bar$var ?= 'default val' -是不是真的有可能不基于符号的表示,甚至为空凝聚$a ?? 'value-if-null'似乎最好到像$a -elseifnull 'value-if-null'

请记住, ?作为Where-Object常用别名,已经牢固地代表了 _conditional_,因此将这些知识转移到其使用的变体中似乎是合乎逻辑的。

PowerShell 真的是 C# 的入口吗? 我知道这是 10-12 年前的明确意图,但它真的发生了吗? 我怀疑对于大多数 PowerShell 用户来说,C# 不是他们想去的地方。

如果三元条件会发生,我更愿意看到类似的东西
$value = $trueVal -if $a -eq $b -else $falseVal

正如@vexx32所提到的

对于普通 PowerShell 用户来说,这更有意义。

@mklement0我对 $psitem 的评论是基于我的个人经验。 如果你有不同的经历,它不会使我的经历无效

我知道这是 10-12 年前的明确意图

是的,在 Jeffrey 的早期 MVP 峰会上。 从那以后我再也没有听到任何不同的声音。

此外,几乎所有的条件/循环结构都来自 C#(和 C 谱系)、 if {}while {}do {} while 、 switch {} , for {} , foreach {} , try {} catch {} finally {}`。 对我来说,这个条件结构也有意义。

不过,这些是语言关键字,@rkeithhill。 运营商完全不同。

我认为您会发现 PowerShell 中使用的绝大多数运算符与它们的 C# 等效运算符完全不同。 PS 团队非常清楚地为大多数运算符选择了更具描述性的语法。

我认为三元行为应该在更详细的可用语法选项之后进行。 PowerShell 可能被认为是 C# 的“入口”,但这并不意味着它应该继承其更多的符号语法。 的确,有很多地方已经煞费苦心地避免了

考虑一下,如果您愿意,您对符号语法的论证植根于其他常见编程语言如何表示这个概念。 PowerShell 并没有在这篇文章中走这条路,而是更喜欢使用尽可能合理的描述性语法。 仅仅因为那些已经有 C# 使用经验的人熟悉这种语法肯定不是使用它的理由。

如果 PowerShell 是 C# 或任何其他语言的“入门”语言(我觉得到目前为止它做得相当好),那么我们需要考虑这里的最低公分母,并考虑最没有经验的人会发现什么理智直觉

我并不是说我提供的解决方案就是这样,但我认为从这个角度来看,他们可能朝着更明智的方向发展。

@vexx32
这些运营商呢?

.
=
[]
,
+ - * / %
++ --
+=  -=  *=  /= %=

一般来说,我同意遵循 C# 的做法并不总是合适的,并且应该优先保留 PowerShell 的精神。

相反,如果相同的语法看起来似乎合理,我建议不要偏离 C#,对我而言,手头的建议 - 以及 #3240 - 就是一个例子。

如果我们抛开其他语言:

  • ?的当前语义似乎可以扩展到提议的运算符。

  • 如果您看到提议的 _related_ 运算符的价值 - 空浸( ?. )、空合并( ?? )和空条件赋值( ?= )-然后选择对于像-then / -else这样冗长的三元形式,如果您希望所有这些相关的运算符都反映一个共性(它们显然在概念上具有),则不是一种选择。

一个特征越奇特,冗长就越重要。

越频繁使用的特征,简洁就越重要。 而基于符号的表示的抽象性通过反复接触语法不再是一个问题——就像* ,例如。

与我讨论的所有运营商都属于后一类。


@理查德西达威

我对 $psitem 的评论是基于我的个人经验。 如果你有不同的经历,它不会使我的经历无效

是的,您的评论基于_个人_经验。
我的基于来自流行问答网站 Stack Overflow 的_分析数据_,以推断_一般_使用模式(在规定的限制范围内)——这与我的个人经验无关。

如果您认为您的个人观察反映了“超个人”的真相,那么您可以认为我的评论无效的唯一原因 - 您在评论中没有提出这样的主张。 你是故意的吗? 如果是这样,我们需要讨论_那个_。

几乎所有这些运算符都是数学运算符,含义相对清晰, @mklement0 😄

三元运算符是条件运算符,PS 的布尔/条件运算符的 _all_ 具有更详细的形式: -and-or-eq-ne , -contains

但是,由于需要周围的功能和相关的运算符,我同意这种简写可能是有意义的。 但我认为,“标准”三元语法并不是特别的直观对于我们这些谁没有被反复暴露于它了。

运算符是数学运算符

在列出的那些中,只有+ - * / %具有(纯粹的)数学意义,但清楚理解的方面也适用于其他方面(除了= ,因为它经常与等式测试混淆)。

比较<condition> ? <if-true> : <else>的更好构造是if _statement_,而不是其他运算符。 虽然if肯定更冗长,但三元运算正是要解决这个方面(除了是一个真正的、可组合的表达式,与if )。

肯定有一系列简洁,但是,正如您所说,为了适应以一致方式提出的所有相关运算符,基于符号的语法是有意义的。

对于我们这些尚未反复接触过的人。

嗯,这有望很快改变。 😁
重点,但 (a) 语法易于解释并且具有与if语句相同的概念复杂性,并且 (b) 重复暴露应该有助于记忆保留。

@mklement0您如何建议将?视为有效的名称字符? 突破性变化? 我认为使用 powershell core 的人对 powershell 非常精通,并且额外的语法(在其他语言中已经存在了近 50 年)不会成为障碍。 如果他们想要更详细的内容,他们总是可以使用if/else

?只是命令模式下的有效别名; 在表达模式的所有变体中,它目前只是一个无效字符。 没有碰撞。

如果您尝试输入此代码,它只会出错:

$Value = $true
$Value ? "Hello!" : "Goodbye!"

结果:

At line:1 char:8
+ $Value ? "Hello!" : "Goodbye!"
+        ~
Unexpected token '?' in expression or statement.
+ CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken

@vexx32

$what? # <- example of a valid variable name

在他的 null-soaking 示例中: $var?.maybenull()不在乎那里有一个问号,如果有人试图过度浓缩,他们的三元将破裂。

抱歉,这主要是在另一个问题中讨论的,所以我不认为你指的是那个。

我们是否可以排除它成为有效的变量名角色取决于 PS 团队,但我倾向于认为,默认情况下阻止它被视为变量名角色不会有太大影响。 我认为我从未见过有人真正使用?作为变量名的一部分。

@vexx32是的,我应该在那里提出这个问题。 如果不注意范围界定,这可能会产生额外的影响(虽然这已经在字符串扩展中看到,所以人们应该有点熟悉它):

$var = $test?$thing1:$thing2

但对于我们这些生活在贝壳中的人来说,我可能在边缘情况下分得太多。

更正:

$var = ${test}?${thing1}:$thing2

@mklement0 - 我不一定同意:

比较好的结构?to 是 if 语句,而不是其他运算符。 虽然 if 肯定更冗长,但三元运算正是要解决这个方面(除了是一个真实的、可组合的表达式,与 if 不同)。

具体来说,存在三元运算符是因为 C/C# 是面向语句的语言,但需要条件表达式。

在面向表达式的语言(例如 F# 或 Rust)中,没有简洁的语法,因为它被认为是不必要的。 我认为这个关于 Rust删除三元运算符的旧讨论很有趣。

我在 Rust 中真正喜欢的一件事是使用?操作符进行错误处理。 我没有在 PowerShell 中使用?的具体建议,但感觉?可以更好地用于错误处理而不是条件表达式。

@TheIncorrigible1@vexx32 :是的,空浸在技术上将是一个突破性的变化,但希望是类型bucket 3 (确实,让我们继续讨论); 对于三元运算,建议在?之前使用{...} / 空格来消除歧义似乎可以解决该问题。

@lzybkr :

具体来说,存在三元运算符是因为 C/C# 是面向语句的语言,但需要条件表达式。

好吧,在 PowerShell 流控制语句中,例如if是 _half_-表达式; 在_simple_表达式中,建议的三元运算是等效的; 在 _nested_ 中,它不会:

$foo = $True  ?     1   :      0    # proposed ternary
$foo = if ($True) { 1 } else { 0 }  # equivalent `if` statement
$foo = 1 + ($True  ?     1   :      0)   # nesting OK; note that + would have higher precedence
$foo = 1 + if ($True) { 1 } else { 0 }  # !! doesn't work
$foo = 1 + (if ($True) { 1 } else { 0 })  # !! doesn't work, even with parentheses
$foo = 1 + $(if ($True) { 1 } else { 0 })  # only $(...) (and situationally @(...)) work

需要$() / @()不仅仅是语法上的不便:它还具有行为和性能影响。

也就是说,我_希望_诸如ifforeach的语句是真正的表达式(另外两个当前失败的例子: foreach ($i in 1..5) { $i } | Write-Outputforeach ($i in 1..5) { $i } > out.txt )。
我不知道足以判断它们是否_不能_,但是和/或是否存在向后兼容性问题。
另见:#6817


如果if在 PowerShell 中成为一个完整的表达式,那么您可以提出导致从 Rust 中删除三元条件的论点:它不再是 _necessary_。

然而,我提出这个提议的动机从来不是_必要性_——它是关于简洁、方便和可读性(视觉混乱)。


我没有具体的建议可以使用? 在 PowerShell 中,但感觉就像? 可以更好地用于错误处理而不是条件表达式。

我认为引入?与在 C# 中根本不同的语义将是一个永久混乱的根源。

另外,PowerShell 错误处理方面的改进非常值得讨论。

如果我们正在寻找一种简洁但不直观的 If/Then/Else 替代方案,我们已经有了。

( 'False', 'True' )[( Test-Condition )]

它适用于表达式。

"This statement is " + ( 'False', 'True' )[( Test-Condition )]

@TimCurwick :这很简洁(而且更晦涩),但不等效:建议的三元条件是 _short-circuiting_(就像if语句一样),而您的语法总是评估 _both_ 替代方案。

也就是说,假设您知道所述限制,您的语法肯定是当前可用的下一个最好的东西。

关于如何在 PowerShell 中显示三元选项的讨论,有没有人考虑过与-replace / .replace()使用的格式相同的选项?

$a -eq $b -ternary $a,$c
$true -ternary 1,0

或者

($a -eq $b).ternary($a,$c)
($true).ternary(1,0)

这将清楚地表明操作员正在执行一个三元操作,字面上将其称为ternary 。 它很冗长,但编写起来仍然很短,并且它利用了-operator $first,$second的现有常见行为,因此对于所有经验范围的 powershell 用户来说,它应该感觉很熟悉

🤔 它可能有效,但它会比任何提议的替代方案都更尴尬。 -replace是这样工作的,因为它只接受一个实际的参数数组。 .Replace()不是由 PS 团队管理的——它是 .NET System.String类上的一个方法。

如果我们尝试使用这些语法中的任何一种,则意味着使用 ETS 方法(这很好,但往往会在创建需要附加的对象时增加一些性能开销),或者使用运算符版本您建议,我们将无法轻松地将数组作为参数。

如果没有在解析器中对这样的运算符进行特殊处理,我们将无法短路。 其他语言中的三元语法通常存在,因为您_不希望_实际评估这两个选项; 如果只需要评估正确的分支,而不是必须完全评估两个选项(这可能会带来一些显着的副作用),则计算时间会更快。

并且由于这已经需要特殊的外壳,因此为它引入新的语法会更有效,以最大程度地减少混淆(拥有看起来像数组但不能像数组一样使用的东西会有点误导;它例如,不支持提前创建“数组”并将其作为变量传递)。 方法参数已经与数组语法有点冲突的事实通常已经具有误导性。 我不认为我想在混合中添加逗号的 _third_ 变体行为。

@PowerShell/powershell-committee 详细讨论了这个问题,我们并不都同意,但大多数人同意拥有这个运算符是有价值的,并且与 C# 语法保持一致,保持?:作为预期是大多数用法将来自 C# 开发人员。 此功能将是实验性的,等待实际使用反馈。

@SteveL-MSFT 所以这意味着该功能正在向 7.0 推进? 它会破坏能够在其符号中使用?变量的兼容性吗?

@TheIncorrigible1是的,此功能正在 PS7 中向前发展。 它不应该破坏与使用?别名的兼容性。 在查看试图区分Where-Objectternary的脚本时,会担心?视力,但我们会看到用户对此的反馈。 通常,我们不希望大多数用户使用此运算符,但这不应阻止它继续前进。

@SteveL-MSFT 我的意思是名称为$isValid?或类似名称的变量。 这些是当前 PS 迭代中的有效令牌。

@TheIncorrigible1

如前所述,在第一个操作数和?之间需要空格解决了这个问题,对我来说这是一个非常合理的解决方案:

  • : _also_ 周围需要空格,因为$true ? $number:42类的东西不起作用,因为$number:42会_作为一个整体_被解释为单个变量引用。

  • 虽然 C# _does_ 允许true?number:42 ,但我认为我们不需要 - 或者实际上可以 - 担心该级别的兼容性。 我个人看重简洁,但不以牺牲可读性为代价; 即使我_可以_写$true?$number:42 ,我也不会。

(当 (hint,hint) 我们实现空条件访问时,向后兼容性确实会成为一个问题。PowerShell对标识符名称的许可通常是有问题的,正如那艘船已经航行了

是的,我认为留下空白要求是明智的。 毕竟,它已经足够简洁了。 😁

原型非常努力地在三元运算符的上下文中以不同的方式解析包含?: (我们知道我们正在期待一个表达式)。 所以你可以写类似${isWindows}?12:47
123?1:23这样的数字今天被标记为通用标记,这在我们知道我们期待一个表达式的情况下根本没有用。

对于变量,完全没有改变?:用于变量名的方式,因为变量是一个表达式。

好点,@daxian-dbw; 我忘记了{...}可用于解决任何变量名边界歧义,所以我猜代码高尔夫球手可以使用类似${isWindows}?${number}:47

我们现在可以关闭这个吗?

通过 #10367 关闭

此页面是否有帮助?
0 / 5 - 0 等级