1 minute read

Most Rubyists know they can use literals, classes, ranges and regular expressions in the when branches of a case expression:

case something
when Array then ...
when 1..100 then ...
when /some_regexp/ then ...
end

As you probably know case relies on the === (a.k.a. the case equality operator) being defined for the supplied conditions. Ruby will convert the above code to something like:

case something
when Array === something then ...
when 1..100 === something then ...
when /some_regexp/ === something then...
end

Perhaps somewhat surprisingly === is also defined in the Proc class, used to create procs and lambdas. It’s defined to simply issue a Proc#call with the right-hand side argument of === as an argument:

is_even = ->(n) { n.even? }

is_even === 5 # => false

# same as
is_even.call(5)

This gives us the possibility to leverage procs and lambdas as the conditions for when branches. Here’s a trivial example:

def even?
  ->(n) { n.even? }
end

def odd?
  ->(n) { n.odd? }
end

case x
when even? then puts 'even'
when odd? then puts 'odd'
else puts 'Impossible!'
end

You can also save a few lines by defining the lambdas inline:

case x
when ->(n) { n.even? } then puts 'even'
when ->(n) { n.odd? } then puts 'odd'
else puts 'Impossible!'
end

Things get even better if your lambdas capture some additional arguments. Consider this example checking HTTP response codes:

def response_code?(code)
  ->(response) { response.code == code }
end

case response
when response_code?(200) then 'OK'
when response_code?(404) then 'Not found'
else 'Unknown code'
end

Pretty neat, right?

That’s all for today folks! Code long and prosper!

Tags:

Updated: