52

I am reading the Module documentation but can't seem to understand their differences and which should be used where.

How is the eval different than exec?

Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
Kamilski81
  • 14,409
  • 33
  • 108
  • 161

3 Answers3

94

I'm going to answer a bit more than your question by including instance_{eval|exec} in your question.

All variations of {instance|module|class}_{eval|exec} change the current context, i.e. the value for self:

class Array
  p self                     # prints "Array"
  43.instance_eval{ p self } # prints "43"
end

Now for the differences. The eval versions accepts a string or a block, while the exec versions only accept a block but allow you to pass parameters to it:

def example(&block)
  42.instance_exec("Hello", &block)
end
example{|mess| p mess, self } # Prints "Hello" then "42"

The eval version does not allow to pass parameters. It provides self as the first parameter, although I can't think of a use for this.

Finally, module_{eval|exec} is the same as the corresponding class_{eval|exec}, but they are slightly different from instance_{eval|exec} as they change what is the current opened class (i.e. what will be affected by def) in different ways:

String.instance_eval{ def foo; end }
Integer.class_eval  { def bar; end }

String.method_defined?(:foo)            # => false
String.singleton_methods.include?(:foo) # => true
Integer.method_defined?(:bar)           # => true

So obj.instance_{eval|exec} opens the singleton class of obj, while mod.{class|module}_{eval|exec} opens mod itself.

Of course, instance_{eval|exec} are available on any Ruby object (including modules), while {class|module}_* are only available on Module (and thus Classes)

Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
  • 1
    Note: when you module_eval lambda, it passes the module itself to lambda as the first parameter. module_exec doesn't. – Nakilon Sep 16 '14 at 10:21
  • 1
    I didn't realize that. I can't think of a single case where that would be of any use (use `self` instead), but I've edited my answer for completeness. – Marc-André Lafortune Sep 16 '14 at 17:35
  • Thank you @Marc-AndréLafortune, but in the above example, where is the `mess` parameter coming from? – BenKoshy Feb 03 '20 at 22:56
  • @BKSpurgeon the second reference to `&block`, where `"Hello"` is passed as the argument for `mess` – Jonathan Jun 29 '20 at 16:02
  • I've just discovered that on, for example, ::Oga::XML::Element I can call both instance_ and module_. Wanted to know the difference but answers here don't tell it. This article says "In effect, class_eval is an alias for module_eval." https://medium.com/rubycademy/ruby-class-eval-vs-module-eval-6c3cc24a070 – Nakilon May 07 '22 at 05:42
6

To answer your last question first, eval (in all its variations) is completely different from exec. exec $command will start a new process to run the command you specify and then exit when that finishes.

class_eval and module_eval have the power to redefine classes and modules -- even those that you yourself did not write. For example, you might use class eval to add a new method that did not exist.

Fixnum.class_eval { def number; self; end }
7.number # returns '7'

class_eval can be used to add instance methods, and instance_eval can be used to add class methods (yes, that part is very confusing). A class method would be something like Thing.foo -- you're literally calling the foo method on the Thing class. An instance method is like the example above, using class_eval I've added a number method to every instance of Fixnum.

Okay, so that's the *_eval class of methods. The exec methods are similar, but they allow you to look inside a class and execute a block of code as though it was defined as a method on that class. Perhaps you have a class that looks like this:

class Foo
  @@secret = 'secret key'
  @@protected = 'some secret value'
  def protected(key)
    if key == @@secret
       return @@protected
    end
  end
end

The class Foo is just a wrapper around some secret value, if you know the correct key. However, you could trick the class into giving you its secrets by executing a block inside the context of the class like so:

Foo.class_exec { @@secret = 'i'm a hacker' }
Foo.protected('i'm a hacker') #returns the value of @@protected because we overwrote @@secret

In general, with a lot of the tools in ruby, you could use any of these to solve a lot of problems. A lot of the time you probably won't even need to unless you want to monkey patch a class some library you use has defined (although that opens up a whole can of worms). Try playing around with them in irb and see which you find easier. I personally don't use the *_exec methods as much as the *_eval methods, but that's a personal preference of mine.

tjarratt
  • 1,692
  • 9
  • 17
0

To avoid ambiguity I'm going to call a method that belongs to (owned by) a singleton class a singleton method. The rest are instance methods. Although one might say that a singleton method of an object is an instance method of its singleton class.

tl;dr Use class_eval/module_eval on a class/module to define instance methods, and instance_eval on a class/module to define class methods (or to be more precise, use instance_eval to define singleton methods). Additionally you can use instance_eval to access instance variables.

A terminology is a bit lacking in this case. ruby maintains a stack of class references (cref for short). When you open/reopen a class, the corresponding class reference is pushed to the stack. And the current class refernece affects where def defines methods (to which class/module they're added).

Now, class_eval/module_eval and class_exec/module_exec are aliases.

The *_exec() variants don't accept strings, and allow to pass arguments to the block. Since the *_eval() variants are mainly used I'll focus on them.

class_eval/module_eval changes cref and self to the receiver (Thing in Thing.module_eval(...)):

instance_eval changes cref to the singleton class of the receiver, and self to the receiver.

Let's see them in action:

class A
  p self          #=> A
  @a = 1
  def initialize
    @b = 2
  end
end
p A.instance_variables      #=> [:@a]
p A.new.instance_variables  #=> [:@b]

@a on a class level adds an instance variable to the class A as an object. I'm adding it here for completeness. But that's not how you add a class variable.

A.instance_eval do
  p self                #=> A
  p @a                  #=> 1
  def m() puts 'm' end
end
sclass = A.singleton_class
p sclass.instance_methods(false).include? :m  #=> true
A.m                                           #=> m

a = A.new
a.instance_eval do
  p self                  #=> #<A:0x00007fc497661be8 @b=2>
  p @b                    #=> 2
  def m2() puts 'm2' end
end
sclass = a.singleton_class
p sclass.instance_methods(false).include? :m2  #=> true
a.m2                                           #=> m2

So, inside instance_eval def adds a singleton method to the receiver (an instance method to the singleton class of the receiver). For a class/module that means a class/module method. For other objects, a method that is available for that particular object.

A.class_eval do
  p self                #=> A
  p @a                  #=> 1
  def m() puts 'm' end
end
p A.instance_methods(false).include? :m  #=> true
A.new.m                                  #=> m

And, inside class_eval def adds an instance method to the receiver itself (the class/module). class_eval is only available for classes/modules.

Also, when class_eval is passed a block, constant/class variable lookup is not affected:

module A
  C = 1
  @@c = 1
  class B
    C = 2
    @@c = 2
  end
  A::B.class_eval { p [C, @@c] }  #=> [1, 1]
  A::B.class_eval 'p [C, @@c]'    #=> [2, 2]
end

The naming is confusing. I might guess that instance in instance_eval suggests that receiver is treated as an instance (allows to change things for a particular instance), and class in class_eval as a class (allows to change things for a class of objects).

x-yuri
  • 16,722
  • 15
  • 114
  • 161