Kernel#eval taking a block

  • Thread starter trans. (T. Onoma)
  • Start date
T

trans. (T. Onoma)

Is there a reason Kernel#eval won't take a block? I wrote this to overcome:

# Evaluate a Ruby source code string (or block) in the binding context
def evalb( str=nil, binding=nil, &blk )
if block_given?
Kernel.eval( "proc {|slf, blk| slf.instance_eval(&blk)}",
binding ).call( binding, blk )
elsif str
Kernel.eval( str, binding )
end
end

Although, I'm not sure it's exactly right --I put it together by a bit of
trial and error.

T.

--
( o _ カラãƒ
// trans.
/ \ (e-mail address removed)

I don't give a damn for a man that can only spell a word one way.
-Mark Twain
 
N

nobu.nokada

Hi,

At Sun, 3 Oct 2004 10:25:37 +0900,
trans. (T. Onoma) wrote in [ruby-talk:114646]:
Is there a reason Kernel#eval won't take a block? I wrote this to overcome:

# Evaluate a Ruby source code string (or block) in the binding context
def evalb( str=nil, binding=nil, &blk )
if block_given?
Kernel.eval( "proc {|slf, blk| slf.instance_eval(&blk)}",
binding ).call( binding, blk )
elsif str
Kernel.eval( str, binding )
end
end

It's evaluated in the Binding/Proc's context, but not in the
context where it was created. I.E., it is equivalent to

binding.instance_eval(&blk)

except that variables `slf' and `blk' will be altered if they
exist in the context of `binding'.

Seems less meaningful.
 
T

trans. (T. Onoma)

Hi,

At Sun, 3 Oct 2004 10:25:37 +0900,

trans. (T. Onoma) wrote in [ruby-talk:114646]:
Is there a reason Kernel#eval won't take a block? I wrote this to
overcome:

# Evaluate a Ruby source code string (or block) in the binding context
def evalb( str=nil, binding=nil, &blk )
if block_given?
Kernel.eval( "proc {|slf, blk| slf.instance_eval(&blk)}",
binding ).call( binding, blk )
elsif str
Kernel.eval( str, binding )
end
end

It's evaluated in the Binding/Proc's context, but not in the
context where it was created. I.E., it is equivalent to

binding.instance_eval(&blk)

except that variables `slf' and `blk' will be altered if they
exist in the context of `binding'.

Seems less meaningful.

Crud. I see. You are ( as always ;) quite correct. Is there anyway to
overcome? Back to the original question: why Kernel#eval can't take a block?

Thanks,
T.
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Kernel#eval taking a block"

|Back to the original question: why Kernel#eval can't take a block?

Because it's useless, for my eyes at least. What do you want to
accomplish by eval with a block?

matz.
 
T

trans. (T. Onoma)

Hi,

In message "Re: Kernel#eval taking a block"

|Back to the original question: why Kernel#eval can't take a block?

Because it's useless, for my eyes at least. What do you want to
accomplish by eval with a block?

How to get locals into evaluation?

class T
def initialize
@x = 1
end
attr_reader :x
def get_binding
cool = "matz"
return binding()
end
end
t = T.new
tb = t.get_binding
eval "cool", tb #=> "matz"
a = proc {|c| c.upcase}
eval "cool = a.call(cool)", tb

NameError: undefined local variable or method `a' for #<T:0x4032f038 @x=1>
from (irb):15:in `get_binding'
from (irb):15:in `get_binding'
from (irb):19

t.
 
D

David A. Black

Hi --

Hi,

In message "Re: Kernel#eval taking a block"



How to get locals into evaluation?

class T
def initialize
@x = 1
end
attr_reader :x
def get_binding
cool = "matz"
return binding()
end
end
t = T.new
tb = t.get_binding
eval "cool", tb #=> "matz"
a = proc {|c| c.upcase}
eval "cool = a.call(cool)", tb

NameError: undefined local variable or method `a' for #<T:0x4032f038 @x=1>
from (irb):15:in `get_binding'
from (irb):15:in `get_binding'
from (irb):19

But if you're eval'ing in another binding, 'a' won't mean anything in
a string or a block, will it? In other words: you're trying to mix
locals from two bindings in one expression, which somewhat defeats the
purpose of having "locals" :)


David
 
T

trans. (T. Onoma)

But if you're eval'ing in another binding, 'a' won't mean anything in
a string or a block, will it? In other words: you're trying to mix
locals from two bindings in one expression, which somewhat defeats the
purpose of having "locals" :)

I see. So this kind of thing just can't happen I take it. (Hmm... I think we
discussed this kind of thing on core once.) It would be nice if we could pass
in locals to the binding:

eval(tb, a) { |a| cool = a.call(cool) }

It might also be nice if this could be done without "stepping on toes" (i.e.
overwriting binding's locals).

T.
 
F

Florian Gross

trans. (T. Onoma) said:
I see. So this kind of thing just can't happen I take it. (Hmm... I think we
discussed this kind of thing on core once.) It would be nice if we could pass
in locals to the binding:

eval(tb, a) { |a| cool = a.call(cool) }

It might also be nice if this could be done without "stepping on toes" (i.e.
overwriting binding's locals).

You can use this workaround:

eval("cool = yield.call(cool)", tb) { a }

And in this case also:

eval("cool = yield(cool)", tb, &a)

Regards,
Florian Gross
 
T

trans. (T. Onoma)

You can use this workaround:

eval("cool = yield.call(cool)", tb) { a }

And in this case also:

eval("cool = yield(cool)", tb, &a)

Oh reeeaaaalllly...... darn it!

LocalJumpError: no block given
from (irb):5:in `get_binding'
from (irb):5:in `get_binding'
from (irb):9

Is this a 1.9 thing?

T.
 
F

Florian Gross

trans. (T. Onoma) said:
LocalJumpError: no block given
from (irb):5:in `get_binding'
from (irb):5:in `get_binding'
from (irb):9

Is this a 1.9 thing?

Yikes, sorry. It only works when no explicit binding is given. :(

So the only way seems using Object._id2ref and interpolation for now.

Regards,
Florian Gross
 
M

Markus

Yikes, sorry. It only works when no explicit binding is given. :(

So the only way seems using Object._id2ref and interpolation for now.


What about:

class T
def initialize
@x = 1
end
attr_reader :x
def get_binding
cool = "matz"
return binding()
end
end
t = T.new
tb = t.get_binding
eval "cool", tb #=> "matz"

# Does not work:
# a = proc {|c| c.upcase}
# so instead:
class <<t; def a(c); c.upcase; end; end

eval "cool = a.call(cool)", tb #"MATZ"

I realize it isn't an exact parallel to what you seemed to be
wanting (but then again, it's hard to guess the "proper" semantics of
hypothetical language extensions). Would it work for what you are
trying to accomplish? If not, why not? I'll admit I don't quite see
the goal, nor understand what overlaying two "local" scopes would mean.

If the above isn't what you want, would something like:

tb[:a] = proc {|c| c.upcase}

(which doesn't work, but at least seems to me to be easier to interpret
the intension of) be a good way of describing what you are trying to do?

-- Markus
 
N

nobu.nokada

Hi,

At Tue, 5 Oct 2004 03:51:20 +0900,
trans. (T. Onoma) wrote in [ruby-talk:114847]:
I see. So this kind of thing just can't happen I take it. (Hmm... I think we
discussed this kind of thing on core once.) It would be nice if we could pass
in locals to the binding:

eval(tb, a) { |a| cool = a.call(cool) }

It might also be nice if this could be done without "stepping on toes" (i.e.
overwriting binding's locals).

eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))
 
T

trans. (T. Onoma)

On Friday 08 October 2004 01:49 am, (e-mail address removed) wrote:
| Hi,
|
| At Tue, 5 Oct 2004 03:51:20 +0900,
|
| trans. (T. Onoma) wrote in [ruby-talk:114847]:
| > I see. So this kind of thing just can't happen I take it. (Hmm... I think
| > we discussed this kind of thing on core once.) It would be nice if we
| > could pass in locals to the binding:
| >
| > eval(tb, a) { |a| cool = a.call(cool) }
| >
| > It might also be nice if this could be done without "stepping on toes"
| > (i.e. overwriting binding's locals).
|
| eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))

What are you?

(Note: if this statement doesn't cross the language barrier well, just know
that it is a big compliment!)

T.
 
M

Markus

On Friday 08 October 2004 01:49 am, (e-mail address removed) wrote:
| Hi,
|
| At Tue, 5 Oct 2004 03:51:20 +0900,
|
| trans. (T. Onoma) wrote in [ruby-talk:114847]:
| > I see. So this kind of thing just can't happen I take it. (Hmm... I think
| > we discussed this kind of thing on core once.) It would be nice if we
| > could pass in locals to the binding:
| >
| > eval(tb, a) { |a| cool = a.call(cool) }
| >
| > It might also be nice if this could be done without "stepping on toes"
| > (i.e. overwriting binding's locals).
|
| eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))

What are you?

(Note: if this statement doesn't cross the language barrier well, just know
that it is a big compliment!)

I agree. That's a very clever hack.

irb> class T
irb> def initialize
irb> @x = 1
irb> end
irb> attr_reader :x
irb> def get_binding
irb> cool = "matz"
irb> return binding()
irb> end
irb> end
=> nil
irb> t = T.new
=> #<T:0x400bee3c @x=1>
irb> tb = t.get_binding
=> #<Binding:0x400b85a0>
irb> eval "cool",tb
=> "matz"
irb> a = proc { |s| s.upcase }
=> #<Proc:0x400b0abc@(irb):33>
irb> eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))
=> nil
irb> eval "cool",tb
=> "MATZ"

So basically, what you have is a getter:

vvvvvvvvvvvvvvv
eval("proc{|cool|}", tb).call(a.call(eval("cool", tb)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

and a setter. We could even abstract them (baby steps here; I realize
this opens up all sorts of possibilities):

def tb.[](v)
eval(v.to_s,self)
end

def tb.[]=(v,x)
eval("proc{|#{v}|}",self).call(x)
end

(Using []= also gives us the assignment chaining semantics).

Very nifty!

-- Markus
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top