如何将多重赋值与三元运算符一起使用?

Posted

技术标签:

【中文标题】如何将多重赋值与三元运算符一起使用?【英文标题】:How to use multiple assignment with a ternary operator? 【发布时间】:2017-11-22 07:21:18 【问题描述】:

这行得通:

foo, bar = 1, 2
foo == 1  #true
bar == 2  #true

这也有效:

baz = true
foo = baz ? 1 : 2
foo == 1  #true

不起作用

foo, bar = baz ? 1, 2 : 3, 4
# SyntaxError: (irb):4: syntax error, unexpected ',', expecting ':'
# foo, bar = baz ? 1, 2 : 3, 4
#                    ^

应该如何格式化才能正常工作?

【问题讨论】:

当解析第三个表达式中的第一个逗号时,会引发异常 "syntax error, unexpected ',', expecting ':'"。那是因为1, 2 不是 Ruby 对象。 @AryaMcCarthy,好问题。我忘了包括错误响应。感谢编辑我的问题的人:) 另外,unexpected ',' 很可能只是 Ruby 尽其所能识别缺陷。我在下面概述了更正的语法。 【参考方案1】:

下面是使用三元运算符进行多重赋值的正确语法:

foo, bar = baz ? [1, 2] : [3, 4]

true 和 false 的返回值必须用括号括起来。

我希望这会有所帮助:)

【讨论】:

这不能回答你的问题。 我同意,这个答案可能会解决原始问题(问题中没有描述),但它不是问题的答案。不知道它是如何获得赞成票的。 它回答(或提供解决方案)“如何使用三元运算符进行多重赋值?”部分。 我回答了我自己的问题。也许我应该更清楚。我并没有完全试图找出 why foo, bar = baz ? 1, 2 : 3, 4 不起作用,而是如何正确格式化语法以使用三元运算符进行多重赋值......为此,我相信它确实解决了问题。我认为最长最长的解释并不总是最好的答案。正如莎士比亚所说,“简洁是智慧的灵魂”。因此,我很乐意修改我的问题以排除“为什么?”为什么它会获得赞成票?因为它解决了如何的问题。【参考方案2】:

foo, bar = baz ? 1, 2 : 3, 4

原因如下:

如果您查看parse.y(Ruby 的语法),三元条件结构arg1 ? arg2 : arg3 的参数需要arg(一个参数):

arg     : lhs '=' arg_rhs
        | # ...
        | arg '?' arg opt_nl ':' arg
        | # ...

arg_rhs : arg
        # ...

如上所示,赋值lhs = rhs 也是arg。但是多重赋值mlhs1, mlhs2 = mrhs1, mrhs2 是一个语句

stmt    : # ...
        | mlhs '=' mrhs_arg
        | # ...
        | expr
        ;

虽然参数可以用作表达式

expr    : # ...
        | arg
        ;

如上所示,表达式可以用作语句,反之则不成立:语句并不总是有效的表达式,表达式也不总是有效的参数。

此外,当你有[1, 2]时,它是一个数组,它是一个有效的arg,它也是一个有效的arg_rhs,它可以放在arg : lhs '=' arg_rhs的右侧。 1, 2 不是一个有效的arg,但它一个有效的mrhs_arg(多个右侧的参数组合,或者有多个逗号分隔的值,例如foo, bar = 1, 2,@ 987654341@甚至foo, bar = 1, *[2],或者像foo, bar = [1, 2]这样解构数组值):

mrhs_arg : mrhs
         | arg_value
         ;

mrhs     : args ',' arg_value
         # ...
         | args ',' tSTAR arg_value
         # ...
         | tSTAR arg_value
         # ...
         ;

所以它正好符合stmt : mlhs '=' mrhs_arg 规则。

最后一条规则也是您的解决方案 foo, bar = baz ? [1, 2] : [3, 4] 有效的原因:baz ? [1, 2] : [3, 4]arg,它也是 arg_value,并且可以在 mrhs_arg : arg_value 规则中使用。但是允许foo, bar = 1, 2 (mrhs : args ',' arg_value) 的显式裸逗号规则不能与条件一起使用,因为它明确需要至少两个逗号分隔的参数——这不可能是条件的结果。

tl;dr: 因为多重赋值的解析方式与简单赋值不同。

【讨论】:

以上是关于如何将多重赋值与三元运算符一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

C/C++ 三元运算符实际上是不是具有与赋值运算符相同的优先级?

java多重三元运算符(三目运算符)嵌套

三元运算符

Javascript 三元运算符和赋值

为啥带赋值的三元运算符不返回预期的输出?

右侧的三元/空合并运算符和赋值表达式?