This code does not perform as I expect:
case
when -> { false } then "why?"
else "This is what I expect"
end
# => "why?"
Neither does this
case
when ->(x) {false} then "why?"
else "This is what I expect"
end
# => "why?"
The first then clause is executed in both cases, which must mean that the lambda I supply to the when clause is not being called. I understand that the case equality operator === should be called on whatever the subject of the when clause is. I am wondering what goes on the other side of the === when there is no argument supplied to case. I was thinking it might be nil, but it can't be:
-> {false} === nil
# => ArgumentError: wrong number of arguments (1 for 0)
->(x) {false} === nil
# => false
This performs as expected and, if it were being executed, would lead to my expected case results or an exception. Can someone explain the results above? It seems that the case equality operator isn't being used at all, and yet the first when clause is evaluating to true. BTW, I am doing this because the output of a case can be used for variable assignment and it is less wordy then having several elsif clauses. I would like to be able to use arbitrary Procs in a case statement with no argument.
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
outputs:
why?
why?
This is what I expect
As The Pickaxe ( http://pragprog.com/book/ruby3/programming-ruby-1-9 ) says, there are two forms of case statement.
The first allows a series of conditions to be evaluated, executing code corresponding to the first condition that is true: case when ‹ boolean-expression ›+ ‹ then › ...
The second form of a case expression takes a target expression following the case keyword. case target when ‹ comparison ›+ ‹ then › ...
In your case (case without target) any expression that is not false or nil (such as a Proc or the string 'cat') evaluates to true. The Proc is not executed, unless you call it.
You can use a case statement without a parameter to act similar to an if statement. For example:
case
when x > 0 then puts "positive"
else puts "negative"
end
You're assuming that it's trying to compare to nil, which isn't the case. Rather, when there's no parameter, the case statement is only testing for a "truthy" value (anything except nil and false). So when it hits your first when statement, it's checking to see if your Proc (meaning the actual ruby Proc object, not the results of executing your Proc) is nil or false, which isn't. Since it's "truthy", that code gets executed.
Try this, and you'll notice the Proc never even gets called/executed (you'll only see "bar", not "foo"):
case
when -> { puts 'foo' } then puts 'bar'
else puts "This line will never be printed"
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With