如何使用三元运算符进行多重赋值?

时间:2017-06-19 23:15:28

标签: ruby-on-rails ruby variable-assignment ternary-operator

这有效:

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
#                    ^

如何对其进行格式化以使其有效?

2 个答案:

答案 0 :(得分:8)

  

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,可以放在{{1}的右侧}}。 arg : lhs '=' arg_rhs不是有效的1, 2,但 是有效的arg(多个右侧构建的参数,其中包含多个以逗号分隔的值例如mrhs_argfoo, bar = 1, 2或甚至foo, bar = *[1, 2],或者解析像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中使用1}}规则。但是使用允许mrhs_arg : arg_valuefoo, bar = 1, 2)的显式裸逗号的规则不能与条件一起使用,因为它明确要求至少两个以逗号分隔的参数 - 这不是条件的可能结果。

tl; dr:因为多次分配的解析方式与简单分配不同。

答案 1 :(得分:6)

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

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

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

我希望这会有所帮助:)