Skip to content

Instantly share code, notes, and snippets.

@lawrencepit
Forked from DylanFM/gist:49850
Created January 21, 2009 09:07
Show Gist options
  • Save lawrencepit/49898 to your computer and use it in GitHub Desktop.
Save lawrencepit/49898 to your computer and use it in GitHub Desktop.
# Consider:
def parse(*options)
if options[0].is_a?(Symbol)
if options[0] == :foo
"foo!"
elsif options[0] == :bar
"bar!"
elsif options[0] == :force
if options[1] == "foo"
"foo?"
elsif options[1] == "bar"
"bar?"
elsif options[1] == "foobar"
"foobar!"
end
end
elsif options[0].is_a?(Class)
options.shift.class_eval { define_method(*options) }
else
"Something else"
end
end
parse(:force, "foobar") # => foobar!
parse(String, :ehlo, lambda {"hello world"}) # => #<Proc:>
"erm".ehlo # => hello world
# This is a rather simple and silly example, but imagine you have a bit
# more complicated possibilities in terms of options and it's conditions:
# you'd get ugly looking nested code with lots of case and if-else statements.
# And mostly one huge method implementation.
# Instead, it would be nicer if it was like this:
fun parse(:foo) { "foo! "}
fun parse(:bar) { "bar!" }
fun parse(:force, "foo") { "foo?" }
fun parse(:force, "bar") { "bar?" }
fun parse(:force, "foobar") { "foobar!" }
fun parse(String, Array) { |klazz, m| klazz.class_eval { define_method(*m) } }
fun parse(Object) { "something else" }
# This way it looks more clear which conditions are met for a certain
# output to occur. You'd call it the same way as before:
parse(:force, "foobar") # => foobar!
parse(String, :ehlo, lambda {"hello world"}) # => #<Proc:>
"erm".ehlo # => hello world
# Other possibilities would be
fun parse(/^posts/(.*)/edit$/) { |match| puts "Edit post #{match[1]}" }
fun parse(:port, Integer) { |sym, port| puts "Received port #{port}"}
# etc.
# So ruby can't parse the above examples using fun.
# However, with some cleverness you could trick ruby into
# parsing this, which is what I was looking into.
# You'd have to use ruby2ruby and ParseTree.
# Alternative you could do it like this:
fun :parse, :force, "foobar" { "foobar" }
# which does parse straight in ruby, and which
# is basically how the functor gem works
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment