Kernel#eval taking a block

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

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

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

Thanks,
T.

···

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.

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.

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.

···

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?

Hi --

···

On Tue, 5 Oct 2004, trans. (T. Onoma) wrote:

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

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" :slight_smile:

David

--
David A. Black
dblack@wobblini.net

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.

···

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" :slight_smile:

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

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

···

--
Nobu Nakada

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.

···

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)

What are you?

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

T.

···

On Friday 08 October 2004 01:49 am, nobu.nokada@softhome.net 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)))

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):9

Is this a 1.9 thing?

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

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

Regards,
Florian Gross

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

class T
    def initialize
     @x = 1
   end
   attr_reader :x
   def get_binding
     cool = "matz"
     return binding()
   end
end

=> nil

t = T.new

=> #<T:0x400bee3c @x=1>

tb = t.get_binding

=> #<Binding:0x400b85a0>

eval "cool",tb

=> "matz"

a = proc { |s| s.upcase }

=> #<Proc:0x400b0abc@(irb):33>

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

=> nil

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

···

On Fri, 2004-10-08 at 03:51, trans. (T. Onoma) wrote:

On Friday 08 October 2004 01:49 am, nobu.nokada@softhome.net wrote:

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

···

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

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