Created
May 12, 2016 15:24
-
-
Save 5alamander/3a91e9ef10466c6bd7240dbaf3567c4b to your computer and use it in GitHub Desktop.
Ruby binding of a Proc
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
# take a note of http://stackoverflow.com/questions/10058996/changing-the-binding-of-a-proc-in-ruby | |
class Proc | |
def call_with_vars(vars, *args) | |
Struct.new(*vars.keys).new(*vars.values).instance_exec(*args, &self) | |
end | |
end | |
# test | |
lambda { foo }.call_with_vars(:foo => 3) # => 3 | |
lambda { |a| foo + a }.call_with_vars({:foo => 3}, 1) # => 4 |
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
class LookupStack | |
def initialize(bindings = []) | |
@bindings = bindings | |
end | |
def method_missing(m, *args) | |
@bindings.reverse_each do |bind| | |
begin | |
method = eval("method(%s)" % m.inspect, bind) | |
rescue NameError | |
else | |
return method.call(*args) | |
end | |
begin | |
value = eval(m.to_s, bind) | |
return value | |
rescue NameError | |
end | |
end | |
raise NoMethodError | |
end | |
def push_binding(bind) | |
@bindings.push bind | |
end | |
def push_instance(obj) | |
@bindings.push obj.instance_eval { binding } | |
end | |
def push_hash(vars) | |
push_instance Struct.new(*vars.keys).new(*vars.values) | |
end | |
def run_proc(p, *args) | |
instance_exec(*args, &p) | |
end | |
end | |
class Proc | |
def call_with_binding(bind, *args) | |
LookupStack.new([bind]).run_proc(self, *args) | |
end | |
end | |
# test | |
l = lambda { |a| local + func(2) + some_method(1) + var + a } | |
local = 1 | |
def func(x) x end | |
class Foo < Struct.new(:add) | |
def some_method(x) x + add end | |
end | |
stack = LookupStack.new | |
stack.push_binding(binding) | |
stack.push_instance(Foo.new(2)) | |
stack.push_hash(:var => 4) | |
p stack.run_proc(l, 5) # => 15 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment