[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

accessing caller's binding implicitly

Ben Bleything

11/10/2006 3:38:00 AM

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-histo...

5 Answers

dblack

11/10/2006 3:50:00 AM

0

Trans

11/10/2006 4:46:00 AM

0


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.

James Gray

11/10/2006 3:05:00 PM

0

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&ke...
2Bof%2Bcaller

James Edward Gray II


rubyfan

11/10/2006 6:41:00 PM

0

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-histo...
>
>

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

Ben Bleything

11/10/2006 7:11:00 PM

0

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

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