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 Proc
s 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