如何对三元运算符使用多重赋值?
How to use multiple assignment with a 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
# ^
如何格式化才能使其正常工作?
以下是使用三元运算符进行多重赋值的正确语法:
foo, bar = baz ? [1, 2] : [3, 4]
true 和 false 的 return 值必须括在方括号中。
希望对您有所帮助:)
foo, bar = baz ? 1, 2 : 3, 4
<= this DOES NOT work... why?
原因如下:
如果你查看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
,它可以放在[的右侧=25=]。 1, 2
不是有效的 arg
,但它 是 有效的 mrhs_arg
(多个右侧由参数组成,其中有多个逗号- 分隔值,如 foo, 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
,并且可以在mrhs_arg : arg_value
规则。但是带有允许 foo, bar = 1, 2
(mrhs : args ',' arg_value
) 的明确裸逗号的规则不能与条件一起使用,因为它明确要求至少两个逗号分隔的参数——这不是条件的可能结果。
tl;dr: 因为多重赋值的解析方式不同于简单赋值。
这个有效:
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
# ^
如何格式化才能使其正常工作?
以下是使用三元运算符进行多重赋值的正确语法:
foo, bar = baz ? [1, 2] : [3, 4]
true 和 false 的 return 值必须括在方括号中。
希望对您有所帮助:)
foo, bar = baz ? 1, 2 : 3, 4
<= this DOES NOT work... why?
原因如下:
如果你查看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
,它可以放在[的右侧=25=]。 1, 2
不是有效的 arg
,但它 是 有效的 mrhs_arg
(多个右侧由参数组成,其中有多个逗号- 分隔值,如 foo, 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
,并且可以在mrhs_arg : arg_value
规则。但是带有允许 foo, bar = 1, 2
(mrhs : args ',' arg_value
) 的明确裸逗号的规则不能与条件一起使用,因为它明确要求至少两个逗号分隔的参数——这不是条件的可能结果。
tl;dr: 因为多重赋值的解析方式不同于简单赋值。