lambdas in ruby case (switch)
A little class that has code
and message
attributes (ignore the bizarre HTML link, I can't prevent Markdown from putting it in?):
class Response
attr :code, :message
def initialize(c, m)
@code, @message = c, m # the <a> should not be here...
end
end
...and a method that analyzes those attributes. The interesting part is in a case
, where two of the when
s use some local methods that return lambdas:
def analyze(resp)
def code_is(c)
lambda { |r| r.code == c }
end
def message_is(m)
lambda { |r| r.message == m }
end
case resp
when code_is(200)
"we are good to go"
when message_is("Not Modified")
"not a 200, but it's okay anyway"
else
"uh oh, we got a problem... #{resp.inspect}"
end
end
Now let's see it in action:
response = Response.new(200, "whatever")
puts "first up", analyze(response), ""
response = Response.new(300, "Not Modified")
puts "next", analyze(response), ""
response = Response.new(404, "No Way")
puts "and finally", analyze(response)
This works because the when
s do a ===
, which lambdas/Procs use to run themselves.
More: http://www.aimred.com/news/developers/2008/08/14/unlocking_the_power_of_case_equality_proc/
Written by Alexander
Related protips
3 Responses
Another way of doing this would be to set constants to lambdas and use them as matchers, such as this:
SUCCESS = ->(response) { response.code == 200 }
NOT_MODIFIED =->(response) { response.message == 'Not Modified' }
case response
when SUCCESS then "we are good to go"
when NOT_MODIFIED then "not a 200, but it's okay anyway"
else
"uh oh, we got a problem... #{response.inspect}"
end
@brickattack Yeah, very nice!
So the point is you don't need lambda.call
because the ===
operator (which is what gets called by the case
statement under the hood) invokes that on the lambda by default?