I have this code:
 l = lambda { a }  def some_function      a = 1  end   I just want to access a by the lambda and a special scope which has defined a already somewhere like inside some_function in the example, or just soon later in the same scope as:
 l = lambda { a }  a = 1  l.call   Then I found when calling l, it is still using its own binding but not the new one where it was called.
And then I tried to use it as:
 l.instance_eval do      a = 1      call  end   But this also failed, it is strange that I can't explain why.
I know the one of the solution is using eval, in which I could special a binding and executing some code in text, but I really do not want to use as so.
And, I know it is able to use a global variable or instance variable. However, actually my code is in a deeper embedded environment, so I don't want to break the completed parts if not quite necessary.
I have referred the Proc class in the documentation, and I found a function names binding that referred to the Proc's context. While the function only provided a way to access its binding but cannot change it, except using Binding#eval. It evaluate text also, which is exactly what I don't like to do.
Now the question is, do I have a better (or more elegant) way to implement this? Or using eval is already the regular manner?
Edit to reply to @Andrew:
 Okay, this is a problem which I met when I'm writing a lexical parser, in which I defined a array with fixed-number of items, there including at least a Proc and a regular expression. My purpose is to matching the regular expressions and execute the Procs under my special scope, where the Proce will involved some local variables that should be defined later. And then I met the problem above.
 Actually I suppose it is not same completely to that question, as mine is how to pass in binding to a Proc rather than how to pass it out.
@Niklas: Got your answer, I think that is what exactly I want. It has solved my problem perfectly.
There are only two main differences. First, a lambda checks the number of arguments passed to it, while a proc does not. This means that a lambda will throw an error if you pass it the wrong number of arguments, whereas a proc will ignore unexpected arguments and assign nil to any that are missing.
To keep track of the current scope, Ruby uses bindings, which encapsulate the execution context at each position in the code. The binding method returns a Binding object which describes the bindings at the current position.
Procs are objects, blocks are notA proc (notice the lowercase p) is an instance of the Proc class. This lets us call methods on it and assign it to variables. Procs can also return themselves. In contrast, a block is just part of the syntax of a method call.
You can try the following hack:
class Proc   def call_with_vars(vars, *args)     Struct.new(*vars.keys).new(*vars.values).instance_exec(*args, &self)   end end   To be used like this:
irb(main):001:0* lambda { foo }.call_with_vars(:foo => 3) => 3 irb(main):002:0> lambda { |a| foo + a }.call_with_vars({:foo => 3}, 1) => 4   This is not a very general solution, though. It would be better if we could give it Binding instance instead of a Hash and do the following:
l = lambda { |a| foo + a } foo = 3 l.call_with_binding(binding, 1)  # => 4   Using the following, more complex hack, this exact behaviour can be achieved:
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   Basically we define ourselves a manual name lookup stack and instance_exec our proc against it. This is a very flexible mechanism. It not only enables the implementation of call_with_binding, it can also be used to build up much more complex lookup chains:
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)   This prints 15, as expected :)
UPDATE: Code is now also available at Github. I use this for one my projects too now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With