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