Accessing caller's binding implicitly

Hi all,

As part of my IRB shell history hack (shameless plug1), I need to be
able to access the caller’s binding. Essentially, I need to be able to
do this:

def irb_eval( lines, scope )
  eval(lines.join("\n"), scope)
end

irb_eval( ['a = :foo', 'b = :bar'], binding )

… but without explicitly passing the binding. The goal is this:

irb_eval( ['a = :foo', 'b = :bar'] )

puts a
=> :foo

puts b
=> :bar

Is this even possible? As it is, the eval happens inside of irb_eval’s
scope (I’m assuming… wherever it happens, I can’t see the results when
it’s done) which puts a cramp in my plans for world domination via cute
IRB hacks.

Help?

Thanks,
Ben

Hi –

On Fri, 10 Nov 2006, Ben B. wrote:

irb_eval( [‘a = :foo’, ‘b = :bar’], binding )

Is this even possible? As it is, the eval happens inside of irb_eval’s
scope (I’m assuming… wherever it happens, I can’t see the results when
it’s done) which puts a cramp in my plans for world domination via cute
IRB hacks.

Help?

Do you know about Binding.of_caller by Florian G.? I’m not sure
where it’s distributed from but you’ll find it via Google.

David

Ben B. wrote:

irb_eval( ['a = :foo', 'b = :bar'], binding )

Is this even possible? As it is, the eval happens inside of irb_eval’s
scope (I’m assuming… wherever it happens, I can’t see the results when
it’s done) which puts a cramp in my plans for world domination via cute
IRB hacks.

Help?

Unfortuately not. The binding-of-caller hack is “out of order” last I
heard. The only trick you have available that’s a sure thing is to
prepend a block to the end of the call. Eg.

 irb_eval( ['a = :foo', 'b = :bar'] ){}

You can get the scope off of the block via Proc#binding.

I have to comment that since this is so readily done by passing a
block, it seems like it should be trivial just to go ahead and make
binding of caller a built in metaprogramming method. You know, Matz
talks about being tired of the little things and the glacier pace of
Ruby’s development, but it’s little things like this that people have
been requesting again and again for years.

T.

On Nov 9, 2006, at 10:50 PM, Trans wrote:

The binding-of-caller hack is “out of order” last I heard.

http://eigenclass.org/hiki.rb?cmd=view&p=call_stack+0.1.0&key=binding%
2Bof%2Bcaller

James Edward G. II

On Fri, Nov 10, 2006, Phil T. wrote:

end
evaler = IRB_Evaler.new binding
evaler.irb_eval( [‘a = :foo’, ‘b = :bar’] )
puts a #=> foo

It might work, but it brings up another problem, namely that I’m trying
to keep the interface clean for the caller.

Here’s a more complete explanation of the problem, to hopefully give a
little context:

  • There are a bunch of lines in the readline history
  • a caller in irb can request to re-run a number of those (with the h!
    method)
  • The h! method calls irb_eval, a private method, which in turn fetches
    the lines from the history and evals them

So I want to retain the "h! " semantics, but somewhere I need to
get the binding where h! is called. That precludes the previously
mentioned solution of just tacking a block on to the call to get the
block’s binding.

What might work, but I haven’t tried yet, is essentially doing what you
suggest in the .irbrc’s top-level scope and hoping that it is the same
as the irb prompt’s scope.

I’ll write again once I’ve got a chance to try that.

Ben

On 11/9/06, Ben B. [email protected] wrote:

irb_eval( [‘a = :foo’, ‘b = :bar’], binding )

Ben,

I was thinking about this when you asked at the meeting the other
night…

Given that binding_of_caller seems to be broke in 1.8.5, would
something like this work for you?:

class IRB_Evaler
def initialize scope
@scope = scope
end
def irb_eval(lines)
eval(lines.join(“\n”),@scope)
end
end
evaler = IRB_Evaler.new binding
evaler.irb_eval( [‘a = :foo’, ‘b = :bar’] )
puts a #=> foo

Phil