[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Kernel#eval taking a block

T. Onoma

10/3/2004 1:26:00 AM

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.
/ \ transami@runbox.com

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



13 Answers

nobu.nokada

10/4/2004 12:20:00 AM

0

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.

--
Nobu Nakada


T. Onoma

10/4/2004 2:23:00 PM

0

On Sunday 03 October 2004 08:20 pm, nobu.nokada@softhome.net wrote:
> 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.


Yukihiro Matsumoto

10/4/2004 3:11:00 PM

0

Hi,

In message "Re: Kernel#eval taking a block"
on Mon, 4 Oct 2004 23:23:22 +0900, "trans. (T. Onoma)" <transami@runbox.com> writes:

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

10/4/2004 6:00:00 PM

0

On Monday 04 October 2004 11:11 am, Yukihiro Matsumoto wrote:
> Hi,
>
> In message "Re: Kernel#eval taking a block"
>
> on Mon, 4 Oct 2004 23:23:22 +0900, "trans. (T. Onoma)"
<transami@runbox.com> writes:
> |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.


dblack

10/4/2004 6:31:00 PM

0

T. Onoma

10/4/2004 6:51:00 PM

0

On Monday 04 October 2004 02:31 pm, David A. Black wrote:
> > 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" :-)

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.


Florian Gross

10/4/2004 7:50:00 PM

0

trans. (T. Onoma) wrote:

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

10/4/2004 8:31:00 PM

0

On Monday 04 October 2004 03:49 pm, Florian Gross wrote:
> trans. (T. Onoma) wrote:
> > 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)

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.


Florian Gross

10/4/2004 9:10:00 PM

0

trans. (T. Onoma) wrote:

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

Markus

10/5/2004 4:42:00 AM

0

On Mon, 2004-10-04 at 14:10, Florian Gross wrote:
> trans. (T. Onoma) wrote:
>
> >>> 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 }
> > 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.


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