Accessing caller's binding implicitly

Hi all,

As part of my IRB shell history hack (shameless plug[1]), 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

[1]: http://blog.bleything.net/articles/2006/10/21/shell-style-history-for-irb

Hi --

···

On Fri, 10 Nov 2006, Ben Bleything wrote:

Hi all,

As part of my IRB shell history hack (shameless plug[1]), 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?

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

David

--
                   David A. Black | dblack@rubypal.com
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Ben Bleything wrote:

Hi all,

As part of my IRB shell history hack (shameless plug[1]), 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?

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.

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

···

On 11/9/06, Ben Bleything <ben@bleything.net> wrote:

Hi all,

As part of my IRB shell history hack (shameless plug[1]), 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

[1]: http://blog.bleything.net/articles/2006/10/21/shell-style-history-for-irb

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

James Edward Gray II

···

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

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

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! <number>" 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 Fri, Nov 10, 2006, Phil Tomson wrote:

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