Last active
January 4, 2016 09:49
-
-
Save henrik/8604570 to your computer and use it in GitHub Desktop.
Toying with Ruby 2.1 methods returning symbols.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Wrapping | |
def wrap(method_name, &block) | |
# Alternative implementations: either will do the trick. | |
wrap_with_prepend(method_name, &block) | |
#wrap_with_bind(method_name, &block) | |
end | |
private | |
def wrap_with_prepend(method_name) | |
mod = Module.new do | |
define_method(method_name) { |*args, &block| | |
yield super(*args, &block) | |
} | |
end | |
prepend mod | |
method_name | |
end | |
def wrap_with_bind(method_name) | |
original = instance_method(method_name) | |
define_method(method_name) { |*args, &block| | |
yield original.bind(self).call(*args, &block) | |
} | |
end | |
end | |
module ToyWrappers | |
include Wrapping | |
def reverse(method_name) | |
wrap(method_name, &:reverse) | |
end | |
def upcase(method_name) | |
wrap(method_name, &:upcase) | |
end | |
def l33t(method_name) | |
wrap(method_name) { |x| x.tr("aeiotAEIOT", "4310743107") } | |
end | |
def returns(klass, method_name) | |
wrap(method_name) { |rval| | |
rval.is_a?(klass) ? rval : raise("Expected #{klass} but got #{rval.class.name}!") | |
} | |
end | |
def blocky_returns(klass, &block) | |
method_name = yield | |
returns(klass, method_name) | |
end | |
end | |
class Example | |
extend ToyWrappers | |
reverse reverse upcase def example1(greeting, planet) | |
"#{greeting}, #{planet}! Chains of methods!" | |
end | |
l33t \ | |
upcase \ | |
def example2 | |
"Can break the line with a backslash. Blocks – they #{yield}." | |
end | |
returns String, | |
def example3a | |
"No problem!" | |
end | |
blocky_returns(String) { | |
def example3b | |
"No problem either!" | |
end | |
} | |
returns Float, | |
def example3c | |
"Will explode!" | |
end | |
end | |
puts Example.new.example1("Hello", "world") | |
puts Example.new.example2 { "work" } | |
puts Example.new.example3a | |
puts Example.new.example3b | |
puts Example.new.example3c |
For an example of using prepend, see https://github.com/jnicklas/memoit/blob/master/lib/memoit.rb
Updated this gist to include a prepend
solution.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Good idea! Will try that.