accessing caller's binding implicitly

B

Ben Bleything

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
 
D

dblack

Hi --

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 | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
T

Trans

Ben said:
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.
 
P

Phil Tomson

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

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
 
B

Ben Bleything

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top