【发布时间】:2017-03-01 04:40:08
【问题描述】:
以 Ruby 表达式为例:
case
when 3 then "foo"
when 4 then "bar"
end
我惊讶地发现这不是语法错误。相反,它的计算结果为 "foo"!
为什么?这里应用的语法和评估规则是什么?
【问题讨论】:
标签: ruby syntax switch-statement semantics
以 Ruby 表达式为例:
case
when 3 then "foo"
when 4 then "bar"
end
我惊讶地发现这不是语法错误。相反,它的计算结果为 "foo"!
为什么?这里应用的语法和评估规则是什么?
【问题讨论】:
标签: ruby syntax switch-statement semantics
在case 表达式的这种形式中,与计算结果为truthy 值的词汇上第一个when 子句相关联的then 子句被计算。
参见ISO Ruby Language Specification 的§11.5.2.2.4 语义的第 b) 2) 条(粗体强调我的):
语义
case 表达式的求值方式如下:
- a) […]
- 乙。步骤 c) 中的短语“O is matching”的含义定义如下:
- […]
- 如果 case-expression 是 case-expression-without-expression,O 匹配当且仅当 O 是一个真实的对象。
- c) 采取以下步骤:
- when-clauses 按照它们在程序文本中出现的顺序搜索匹配的when-clause,如下所示:
- i) 如果 when-argument 的 operator-expression-list 存在:
- I) 对于它的每个 operator-expression,对其求值并测试结果值是否匹配。
- II) 如果找到匹配值,则不计算其他 operator-expression(如果有)。
- ii) 如果没有找到匹配值,并且 splatting-argument(参见 11.3.2)存在:
- I) 根据 11.3.2 中的描述构造一个值列表。对于结果列表的每个元素,按照列表中相同的顺序,测试它是否匹配。
- II) 如果找到匹配值,则不会评估其他值(如果有)。
- iii) 当且仅当在其 when-argument 中找到匹配值时,when-clause 被认为是匹配的。后面的 when-clauses,如果有的话,在这种情况下不会被测试。
- 如果其中一个 when-clause 匹配,则评估此 的 then-clause 的 compound-statement当子句。 case-expression 的值就是结果值。
- 如果没有一个 when-clause 匹配,并且如果存在 else-clause,则评估 compound-statement else 子句。 case-expression 的值就是结果值。
- 否则,case-expression 的值为
nil。
RDoc documentation 虽然不那么精确,但也指出 真实性 是选择标准,当条件被省略时;并且词汇顺序决定了检查when 子句的顺序(粗体强调我的):
casecase 语句运算符。 Case 语句由一个可选条件(位于
case的参数位置)和零个或多个when子句组成。 第一个匹配条件的when子句(或评估为布尔真值,如果条件为空)“获胜”,并执行其代码节。 case 语句的值是成功的when子句的值,如果没有这样的子句,则为nil。
【讨论】:
3 将不匹配,因为 3 === true 是 false。安德烈的答案实际上是正确的。
根据设计,没有匹配值的case 语句的行为类似于if 语句。
它其实和写作一样:
if 3
'foo'
elsif 4
'bar'
end
【讨论】: