当你有一个没有参数的case语句而when子句是lambdas时会发生什么?

时间:2013-01-21 23:40:22

标签: ruby

此代码无法按预期执行:

case    
when -> { false } then "why?"        
else "This is what I expect"        
end      
# => "why?"

这也不是

case
when ->(x) {false} then "why?"  
else "This is what I expect"
end  
# => "why?"

在这两种情况下都会执行第一个then子句,这必须意味着不会调用我提供给when子句的lambda。我理解,无论===子句的主题是什么,都应该调用大小写等于运算符when。我想知道在===没有提供参数的情况下,case的另一边发生了什么。我原以为它可能是nil,但不能是:

-> {false} === nil
# => ArgumentError: wrong number of arguments (1 for 0)

->(x) {false} === nil
# => false

这会按预期执行,如果正在执行,则会导致我预期的case结果或异常。有人可以解释上面的结果吗?似乎根本没有使用大小写等于运算符,但第一个when子句正在评估true。顺便说一下,我这样做是因为case的输出可以用于变量赋值,并且它不那么冗长,而是有几个elsif子句。我希望能够在没有参数的case语句中使用任意Proc

2 个答案:

答案 0 :(得分:6)

case    
when -> { false } then puts "why?"        
else puts "This is what I expect"        
end

case    
when 'cat' then puts "why?"        
else puts "This is what I expect"        
end

case    
when -> { false }.call then puts "why?"        
else puts "This is what I expect"        
end

输出:

why?
why?
This is what I expect

正如镐(http://pragprog.com/book/ruby3/programming-ruby-1-9)所说,有两种形式的案例陈述。

  

第一个允许评估一系列条件,执行   对应于第一个条件为真的代码:<   boolean-expression> + ...

     

案例表达式的第二种形式采用目标表达式   关注case关键字。 <比较> + <然后>时的案例目标   ...

在您的情况下(case没有目标)任何非falsenil的表达式(例如Proc或字符串'cat')的计算结果为true。除非call,否则不执行Proc。

答案 1 :(得分:5)

您可以使用不带参数的case语句来执行与if语句类似的操作。例如:

case
when x > 0 then puts "positive"
else puts "negative"
end

你假设它正在尝试与nil进行比较,但事实并非如此。相反,当没有参数时,case语句仅测试“truthy”值(除nilfalse之外的任何值)。因此,当它达到您的第一个when语句时,它会检查您的Proc(表示实际的红宝石Proc对象,执行您的{{ {1}})Procnil,而不是false。由于它是“真实的”,该代码被执行。

试试这个,你会注意到Proc甚至从未被调用/执行过(你只会看到"bar",而不是"foo"):

case
when -> { puts 'foo' } then puts 'bar'
else puts "This line will never be printed"
end