Making sense of the various Ruby "eval"s

Hi all,

Unlike other dynamic languages I'm familiar with (Perl, Lisp), Ruby has
more than one form of 'eval', which is quite confusing for Ruby nubies
like myself. I'm trying to make some sense of all the possibilities:

- Kernel#eval -

This one I (almost) understand. It behaves like Perl's eval, with the
difference that it can take a 'binding' which is another Object, or
Proc. In case of the Object I understand that the code 'eval'ed can
access the Object's instance vars. But how does that work with a Proc as
a binding ?

- Object#instance_eval -

Is obj.instance_eval("blah") exactly the same as eval("blah", obj) ? If
the answer to this question is positive, then the string version of
instance_eval is clear. But what about its block version ? How does that
work ? Are the contents of the block just treated as a string ?

- Module#class_eval -

With its synonym module_eval: very similar to Object#instance_eval, just
that all methods are added to a class and not to an object, right ?

Thanks in advance

···

--
Posted via http://www.ruby-forum.com/.

- Kernel#eval -

it's the evil eval, forget it :slight_smile:

- Object#instance_eval -

Is obj.instance_eval("blah") exactly the same as eval("blah", obj) ?

You can give only a Proc/Binding to the evil eval

work ? Are the contents of the block just treated as a string ?

no, the block is executed with self = object

- Module#class_eval -

moulon% cat b.rb
#!/usr/bin/ruby
class A
end

A.instance_eval {
   p self
   def a
      puts "A::a"
   end
}

A.module_eval {
   p self
   def a
      puts "A#a"
   end
}

A.a
A.new.a
moulon%

moulon% ./b.rb
A
A
A#a
moulon%

Guy Decoux

···

A::a

ts wrote:

> - Kernel#eval -

it's the evil eval, forget it :slight_smile:

Forget Kernel#eval or the string version of any #eval ? The first maybe,
but the second is what allows code generation on-the-fly.

> - Object#instance_eval -

> Is obj.instance_eval("blah") exactly the same as eval("blah", obj) ?

You can give only a Proc/Binding to the evil eval

> work ? Are the contents of the block just treated as a string ?

no, the block is executed with self = object

And in the string version, what is 'self' ?
I'm struggling to fully understand the difference between the block and
the string versions ?

> - Module#class_eval -

moulon% cat b.rb
#!/usr/bin/ruby
class A
end

<snip>

OK I think I understand: instance_eval adds instance methods to a class,
and class/module_eval adds class methods to a class. But also
instance_eval can be called on any object, but class_eval can't (it can
be called only on class / module objects). Correct ?

···

--
Posted via http://www.ruby-forum.com/\.

I'm struggling to fully understand the difference between the block and
the string versions ?

the string version is evil :slight_smile:

OK I think I understand: instance_eval adds instance methods to a class,

instance_eval add singleton methods, this is why you can use it with any
objects (not only class, modules).

and class/module_eval adds class methods to a class. But also

no, add instance method for a class. This is why you can use it only with
a class, module.

instance_eval can be called on any object, but class_eval can't (it can
be called only on class / module objects). Correct ?

yes.

Guy Decoux

ts wrote:

> I'm struggling to fully understand the difference between the block
and
> the string versions ?

the string version is evil :slight_smile:

It may be evil but it is necessary. Correct me if I am wrong, but this
is how I see it - the string version of eval is the only way to
differentiate between "evaluation time" and "execution time". Example:

name = '"Mike"'
evaltime = eval "lambda {name = 'Jane'; puts #{name}}";
runtime = eval "lambda {name = 'Jane'; puts name}";

evaltime.call
runtime.call

==> Mike
==> Jane

Unless I'm misunderstanding something, this can be only done with the
string version of eval. Additionally, stitching pieces of code together,
like this:

var = '"Jane"'
estr = "lambda {name =" + var + "; puts name}"

runtime = eval estr
runtime.call

Can also be done only with the string version.

The way I see it, the block version is simply a convenience, making the
code cleaner. It is similar to wrapping a string into a single
(non-interpolating) quote:

class Ab
end

boor = Ab.new

boor.instance_eval {
   p "using block"
   def a
      puts "Ab::a"
   end
}

boor.instance_eval %q{
  p "using %q"
  def b
    puts "Ab::b"
  end
}

boor.a
boor.b

==> "using block"
==> "using %q"
==> Ab::a
==> Ab::b

What have I missed ?

Thanks in advance.
Eli

···

--
Posted via http://www.ruby-forum.com/\.

What have I missed ?

The evilness of eval.

Guy Decoux

As well as the difference in when the code is parsed mentioned in
another post, it's probably worth noting that string eval is slower than
block eval:

$ cat eval_bench2.rb
require 'benchmark'
o = Object.new
Benchmark.bm(10) do |b|
  b.report("eval str:") { 10000.times {o.instance_eval '10.times { |i| l = 300 * i }' }}
  b.report("eval blk:") { 10000.times {o.instance_eval { 10.times { |i| l = 300 * i }} }}
end

$ ruby -v eval_bench2.rb
ruby 1.8.4 (2005-12-24) [i686-linux]
                user system total real
eval str: 0.340000 0.000000 0.340000 ( 0.416134)
eval blk: 0.160000 0.000000 0.160000 ( 0.203212)

In yarv, the difference is even more marked, and from what I can gather
it's likely to stay that way:

$ ruby-yarv -v eval_bench2.rb
ruby 2.0.0 (Base: Ruby 1.9.0 2006-04-08) [i686-linux]
YARVCore 0.4.0 Rev: 497 (2006-05-07) [opts: ]
                user system total real
eval str: 0.820000 0.020000 0.840000 ( 0.836336)
eval blk: 0.060000 0.000000 0.060000 ( 0.105170)

···

On Sat, 2006-05-13 at 14:52 +0900, Eli Bendersky wrote:

ts wrote:

>
> > I'm struggling to fully understand the difference between the block
> and
> > the string versions ?
>
> the string version is evil :slight_smile:
>
[...]
The way I see it, the block version is simply a convenience, making the
code cleaner. It is similar to wrapping a string into a single
(non-interpolating) quote:

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk

ts wrote:

> What have I missed ?

The evilness of eval.

Guy Decoux

Guy,

I would really appreciate a serious answer. The Ruby documentation is
bad, there's no need to tell you that, and I'm trying to understand
things in depth, hence my questions.

I understand that eval can be mis-used, like many other advanced
features.

However, I much prefer a serious to-the-point answer. You have cleared
out a lot for me, and I thank you for that. What is left is my last
question:

Is block eval the same as single-quoted-string eval ?

Thanks in advance

···

--
Posted via http://www.ruby-forum.com/\.

I genuinely have no clue what the difference is between class_eval and
instance_eval. Check out this quick irb session:

irb(main):111:0> class Foo; end
=> nil
irb(main):112:0> Foo.instance_eval { define_method(:foo) { "foo" } }
=> #<Proc:0x00318b00@(irb):112>
irb(main):113:0> Foo.foo
NoMethodError: undefined method `foo' for Foo:Class
        from (irb):113
irb(main):114:0> Foo.new.foo
=> "foo"
irb(main):115:0> class Bar; end
=> nil
irb(main):116:0> Bar.class_eval { define_method(:bar) { "bar" } }
=> #<Proc:0x003078a0@(irb):116>
irb(main):117:0> Bar.bar
NoMethodError: undefined method `bar' for Bar:Class
        from (irb):117
irb(main):118:0> Bar.new.bar
=> "bar"

I would think that since I used class_eval in one and instance_eval in
the other, SOMETHING should be different..

Pat

···

from :0
        from :0

$ cat string.rb
def foo
  instance_eval %{
    387 8sbf fy"(/·%" /·/% "· ·· sdug sdf
  }
end

puts "I can't foresee any problem."

# much later, in code far, far away
#foo

$ ruby string.rb
I can't foresee any problem.
$ cat block.rb
def foo
  instance_eval do
    387 8sbf fy"(/·%" /·/% "· ·· sdug sdf
  end
end

puts "I can't foresee any problem."

# much later, in code far, far away
#foo

$ ruby block.rb
block.rb:4: syntax error, unexpected tINTEGER, expecting kEND
    387 8sbf fy"(/·%" /·/% "· ·· sdug sdf
         ^
block.rb:4: Invalid char `\302' in expression
block.rb:4: Invalid char `\267' in expression
block.rb:4: unterminated string meets end of file
block.rb:4: syntax error, unexpected tSTRING_END, expecting tSTRING_CONTENT or tREGEXP_END or tSTRING_DBEG or tSTRING_DVAR

Another difference:

$ cat eval.rb
def foo_string(str)
  eval str
  instance_eval "var"
end

def foo_block(str)
  eval str
  instance_eval { var }
end

puts foo_string("var = 'some value'")
puts foo_block("var = 'some value'")

$ ruby eval.rb
some value
eval.rb:8:in `foo_block': undefined local variable or method `var' for main:Object (NameError)
        from eval.rb:8:in `foo_block'
        from eval.rb:12

···

On Sat, May 13, 2006 at 05:28:19PM +0900, Eli Bendersky wrote:

ts wrote:

>
> > What have I missed ?
>
> The evilness of eval.
>
> Guy Decoux

Guy,

I would really appreciate a serious answer. The Ruby documentation is
bad, there's no need to tell you that, and I'm trying to understand
things in depth, hence my questions.

I understand that eval can be mis-used, like many other advanced
features.

However, I much prefer a serious to-the-point answer. You have cleared
out a lot for me, and I thank you for that. What is left is my last
question:

Is block eval the same as single-quoted-string eval ?

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

Hi --

I genuinely have no clue what the difference is between class_eval and
instance_eval. Check out this quick irb session:

irb(main):111:0> class Foo; end
=> nil
irb(main):112:0> Foo.instance_eval { define_method(:foo) { "foo" } }
=> #<Proc:0x00318b00@(irb):112>
irb(main):113:0> Foo.foo
NoMethodError: undefined method `foo' for Foo:Class
      from (irb):113
      from :0
irb(main):114:0> Foo.new.foo
=> "foo"
irb(main):115:0> class Bar; end
=> nil
irb(main):116:0> Bar.class_eval { define_method(:bar) { "bar" } }
=> #<Proc:0x003078a0@(irb):116>
irb(main):117:0> Bar.bar
NoMethodError: undefined method `bar' for Bar:Class
      from (irb):117
      from :0
irb(main):118:0> Bar.new.bar
=> "bar"

I would think that since I used class_eval in one and instance_eval in
the other, SOMETHING should be different..

Fear not; it is :slight_smile: Look at what happens when you use def:

class C; end

=> nil

C.instance_eval { def x; 1; end } # singleton method on C

=> nil

C.x

=> 1

C.new.x

NoMethodError: undefined method `x' for #<C:0x35b16c>
         from (irb):4

C.class_eval { def y; 1; end } # instance method of C

=> nil

C.y

NoMethodError: undefined method `y' for C:Class
         from (irb):6

C.new.y

=> 1

C.instance_eval handles the business of C itself, as an object. You'd
get similar results with any_object.instance_eval { def x; 1; end }

C.class_eval takes you into a class definition block for C, where def
is an instance method of C. So it's much more class (and module)
specific in its engineering.

David

···

On Sun, 14 May 2006, Pat Maddox wrote:
         from :0

--
David A. Black (dblack@wobblini.net)
* Ruby Power and Light, LLC (http://www.rubypowerandlight.com)
   > Ruby and Rails consultancy and training
* Author of "Ruby for Rails" from Manning Publications!
   > Ruby for Rails

Mauricio Fernandez wrote:

Is block eval the same as single-quoted-string eval ?

$ cat string.rb
def foo
  instance_eval %{
    387 8sbf fy"(/�%" /�/% "� �� sdug sdf
  }
end

<snip>

Another difference:

$ cat eval.rb
def foo_string(str)
  eval str
  instance_eval "var"
end

def foo_block(str)
  eval str
  instance_eval { var }
end

puts foo_string("var = 'some value'")
puts foo_block("var = 'some value'")

<snip>

OK, thanks - this I understand. The block version of eval checks the
block at compile time for errors, while the string version does not.
This is another plus for the block version, and generally I agree that
it should be used over the string version whenever that is possible.

The string version, however, has its uses, and can do things the block
version can't, as I have shown in my examples. Such uses should be well
thought-out and kept to the minimum, of course.

Eli

···

On Sat, May 13, 2006 at 05:28:19PM +0900, Eli Bendersky wrote:

--
Posted via http://www.ruby-forum.com/\.

Okay so I guess the problem is that I'm using define_method? I don't
understand the difference between define_method and def then.

define_method: "Defines an instance method in the receiver...This
block is evaluated using instance_eval..."

After first reading that, I thought it explained why there was no
difference between using instance_eval or class_eval with
define_method, because define_method uses instance_eval itself.
However isn't self different when I use instance_eval vs class_eval,
so then the inner instance_eval call would operate on a different
self, making the results different?

Pat

···

On 5/14/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

On Sun, 14 May 2006, Pat Maddox wrote:

> I genuinely have no clue what the difference is between class_eval and
> instance_eval. Check out this quick irb session:
>
> irb(main):111:0> class Foo; end
> => nil
> irb(main):112:0> Foo.instance_eval { define_method(:foo) { "foo" } }
> => #<Proc:0x00318b00@(irb):112>
> irb(main):113:0> Foo.foo
> NoMethodError: undefined method `foo' for Foo:Class
> from (irb):113
> from :0
> irb(main):114:0> Foo.new.foo
> => "foo"
> irb(main):115:0> class Bar; end
> => nil
> irb(main):116:0> Bar.class_eval { define_method(:bar) { "bar" } }
> => #<Proc:0x003078a0@(irb):116>
> irb(main):117:0> Bar.bar
> NoMethodError: undefined method `bar' for Bar:Class
> from (irb):117
> from :0
> irb(main):118:0> Bar.new.bar
> => "bar"
>
> I would think that since I used class_eval in one and instance_eval in
> the other, SOMETHING should be different..

Fear not; it is :slight_smile: Look at what happens when you use def:

>> class C; end
=> nil
>> C.instance_eval { def x; 1; end } # singleton method on C
=> nil
>> C.x
=> 1
>> C.new.x
NoMethodError: undefined method `x' for #<C:0x35b16c>
         from (irb):4
         from :0
>> C.class_eval { def y; 1; end } # instance method of C
=> nil
>> C.y
NoMethodError: undefined method `y' for C:Class
         from (irb):6
         from :0
>> C.new.y
=> 1

C.instance_eval handles the business of C itself, as an object. You'd
get similar results with any_object.instance_eval { def x; 1; end }

C.class_eval takes you into a class definition block for C, where def
is an instance method of C. So it's much more class (and module)
specific in its engineering.

David

--
David A. Black (dblack@wobblini.net)
* Ruby Power and Light, LLC (http://www.rubypowerandlight.com)
   > Ruby and Rails consultancy and training
* Author of "Ruby for Rails" from Manning Publications!
   > Ruby for Rails

define_method: "Defines an instance method in the receiver...This
block is evaluated using instance_eval..."

Well, the block is not really evaluated with instance_eval

moulon% cat b.rb
#!/usr/bin/ruby
class A
   def create_method(name, &block)
      self.class.send(:define_method, name, &block)
   end
end

class B
   def a
      A.new.create_method(:a) { def b() end }
   end
end

B.new.a
A.new.a
A.new.b
moulon%

if the block '{ def b() end }' is evaluated with instance_eval, ruby will
create a singleton method, otherwise my script will work.

moulon% ./b.rb
moulon%

Guy Decoux