Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby `when' keyword does not use == in case statement. What does it use?

Tags:

ruby

case

x == User returns true, but case x statement does not run the block associated with User. What's happening here?

u = User.new
# => #<User:0x00000100a1e948>

x = u.class
# => User

x == User
# => true

case x
when User
  puts "constant"
when "User"
  puts "string"
else
  puts "nothing?"
end
# => nothing?
like image 373
maček Avatar asked Sep 21 '10 06:09

maček


People also ask

Can you use || IN case statement Ruby?

You can't use “||” in case names. But you can use multiple case names without using a break between them. The program will then jump to the respective case and then it will look for code to execute until it finds a “break”.

What does case do in Ruby?

Case statement in the Ruby is a way to execute different codes and expressions on the basis of the values provided to the case, case statement in Ruby is similar to basic switch cases in the other programming languages.

What is case expression in Ruby?

It provides an easy way to forward execution to different parts of code based on the value of the expression. There are 3 important keywords which are used in the case statement: case: It is similar to the switch keyword in another programming languages. It takes the variables that will be used by when keyword.

Does Ruby case fall through?

The case statement in Ruby, on the other hand, can be seen as a shorthand for a series of if statements. There is no fallthrough, only the first matching case will be executed.


2 Answers

Case comparisons use === rather than ==. For many objects the behaviour of === and == is the same, see Numeric and String:

5 == 5 #=> true
5 === 5 #=> true

"hello" == "hello" #=> true
"hello" === "hello" #=> true

But for other kinds of object === can mean many things, entirely depending on the receiver.

For the case of classes, === tests whether an object is an instance of that class:

Class === Class.new #=> true. 

For Range it checks whether an object falls in that range:

(5..10) === 6 #=> true

For Procs, === actually invokes that Proc:

multiple_of_10 = proc { |n| (n % 10) == 0 }
multiple_of_10 === 20 #=> true (equivalent to multiple_of_10.call(20))

For other objects, check their definition of === to uncover their behaviour. It's not always obvious, but they usually make some kind of sense..

Here is an example putting it all together:

case number
when 1
    puts "One"
when 2..9
    puts "Between two and nine"
when multiple_of_10
    puts "A multiple of ten"
when String
    puts "Not a number"
end  

See this link for more info: http://www.aimred.com/news/developers/2008/08/14/unlocking_the_power_of_case_equality_proc/

like image 185
horseyguy Avatar answered Oct 23 '22 19:10

horseyguy


In case statement , the comparison is done using === operator.

So your code is translated to following:

case x
when User === x 
    puts "Constant"
when "User" === x
    puts "string"
else 
    puts "nothing"
end

Different class define === in different way:

The Class class define === so that it tests whether the righthand operand (x)is an instance of the class named by the lefthand operand (User). So , It is not surprise that User === x will be evaluated as false. Instead, User === u (u = User.new) is true.

irb(main):001:0> class User
irb(main):002:1> end
=> nil
irb(main):003:0> u = User.new
=> #<User:0xb7a90cd8>
irb(main):004:0> User === u.class
=> false
irb(main):005:0> User === u
=> true
like image 24
pierrotlefou Avatar answered Oct 23 '22 18:10

pierrotlefou