10

I remember something about procs being allowed in case statements in Ruby 2.0, but I can't google it.

I tried checking Ruby 2.0.0 NEWS and How to write a switch statement in Ruby. I also visited http://ruby-doc.org , but the link it had for keywords was for Ruby 1.9, not Ruby 2.0.

Are procs allowed in case statements?

Community
  • 1
  • 1
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338

1 Answers1

23

Yes.

2.0.0p0 :001> lamb = ->(x){ x%2==1 }
#=> #<Proc:0x007fdd6a97dd90@(irb):1 (lambda)> 

2.0.0p0 :002> case 3; when lamb then p(:yay); end
:yay
#=> :yay 

2.0.0p0 :003> lamb === 3
#=> true 

2.0.0p0 :007> lamb === 2
#=> false 

However, this is no different than 1.9.1 since Proc#=== was defined back then. Since ruby-docs seems to have a problem showing this method, to be clear the documentation says that proc === obj:

Invokes the block with obj as the proc's parameter like #call. It is to allow a proc object to be a target of when clause in a case statement.


For the Ruby beginner, then when clause in Ruby's case statements takes the value in the clause and calls the === method on it, passing in the argument to the case statement. So, for example, this code…

case "cats"
  when /^cat/ then puts("line starts with cat!")
  when /^dog/ then puts("line starts with dog!")
end

…runs /^cat/ === "cats" to decide if it's a match; the RegExp class defines the === method to perform regex matching. Thus, you can use your own object in a when clause as long as you define === for it.

Moddable = Struct.new(:n) do
  def ===(numeric)
    numeric % n == 0
  end
end

mod4 = Moddable.new(4)
mod3 = Moddable.new(3)

12.times do |i|
  case i
    when mod4
      puts "#{i} is a multiple of 4!"
    when mod3
      puts "#{i} is a multiple of 3!"
  end
end

#=> 0 is a multiple of 4!
#=> 3 is a multiple of 3!
#=> 4 is a multiple of 4!
#=> 6 is a multiple of 3!
#=> 8 is a multiple of 4!
#=> 9 is a multiple of 3!
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • `l` looks awfully similar to `1` on Stack Overflow. I was wondering for a minute if George Orwell had been put in charge of the math department! (PS: is there any documentation on using procs in a case statement?) – Andrew Grimm May 21 '13 at 04:54
  • I linked to the 1.9.1 docs, but it seems that all modern versions of the docs fail to provide a proper header for the method, making it very confusing. I'll edit the question with the documentation on `Proc#===`. – Phrogz May 21 '13 at 04:57
  • 1
    Thanks, phroggie, for refreshing that `Proc#===` for me. – Boris Stitnicky May 21 '13 at 05:00