Skip to content

Instantly share code, notes, and snippets.

@dkubb
Forked from flazz/gist:838163
Created August 7, 2011 05:21
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save dkubb/1130086 to your computer and use it in GitHub Desktop.
case with predicates
require 'rubygems'
require 'backports' # aliases Proc#=== to Proc#call
rs = (0..10000).to_a.sample(30)
rs.each do |r|
case r
when lambda { |n| n.zero? } then puts "#{r} is zero"
when lambda { |n| (n % 5).zero? } then puts "#{r} is fiven"
when lambda { |n| (n % 4).zero? } then puts "#{r} is fourven"
when lambda { |n| (n % 3).zero? } then puts "#{r} is threeven"
when lambda { |n| n.even? } then puts "#{r} is even"
when lambda { |n| n.odd? } then puts "#{r} is odd"
else
raise 'unpossible'
end
end
@dkubb
Copy link
Author

dkubb commented Aug 7, 2011

This is a ruby 1.8 port of @flazz's code from http://flazz.me/predicates-in-ruby-case-statements (see his fork for original 1.9 specific code)

@avdi
Copy link

avdi commented Aug 7, 2011

I did not realize this about 1.9. That is a huge deal despite being such a small change. A lot of code that might otherwise have been considered "hacky" becomes idiomatic.

@radar
Copy link

radar commented Aug 7, 2011

That is hot. Nice find, Dan.

@dkubb
Copy link
Author

dkubb commented Aug 7, 2011

@avdi me either. I was surprised when I came across this code. Even though the 1.9 only syntax is going to take some getting used to, it looks pretty natural and will certainly clean up some cases, like you say.

@jacortinas
Copy link

That's beautiful, and ridiculously powerful.

@ecin
Copy link

ecin commented Aug 7, 2011

<3

@ernie
Copy link

ernie commented Aug 7, 2011

Very nice. Had been meaning to test if 1.9 did this with ===. If your subject responds to all predicates, you can also have fun with 1.9's Symbol#to_proc: https://gist.github.com/1130320

@emmanuel
Copy link

emmanuel commented Aug 8, 2011

Proc#call as #=== is a wonderful addition, but this is a terrible example. I hope I never see someone actually do this.

Why such a harsh reaction? Because you should use case statements' native capabilities if the predicates are defined in the same scope: https://gist.github.com/1132758.

@dkubb
Copy link
Author

dkubb commented Aug 8, 2011

@emmanuel your gist is how I would probably write this in real production code.

I remember times where I've wished to be able to include more complex logic in a case statement, and have it evaluated at runtime, but I'm coming up blank trying to think of a good example. Anyone else have one?

@emmanuel
Copy link

emmanuel commented Aug 8, 2011

@dkubb

I agree that this opens terrific options for new types of idiomatic Ruby. I would love to see more examples of how people are using this for great justice, but I suspect such examples will be ill-suited to explication in gist form, by virtue of the substance of my complaint.

To be clear, my point is that this specific example should not be emulated. If the predicates are statically defined in the same scope as a case statement, do the simple thing: use the case statement as Matz intended :P

...pardon me while I continue turning into a cantankerous old grump...

@ernie
Copy link

ernie commented Aug 8, 2011

I'd still very much like to have &:method work in when arg lists. I spent some time trying to hack parse.y over the weekend, actually, to see if I could make it work in some frankenstein-like manner, but my version of bison seemed not to be playing nicely. :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment