# Eval, module\_eval, define\_method, and all that

**URL:** <https://www.ruby-forum.com/t/eval-module-eval-define-method-and-all-that/120519>\
**Category:** Ruby\
**Created:** [November 17, 2007, 10:12pm UTC](https://www.ruby-forum.com/t/eval-module-eval-define-method-and-all-that/120519 "2007-11-17T22:12:22Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [November 17, 2007, 10:12pm UTC](https://www.ruby-forum.com/t/eval-module-eval-define-method-and-all-that/120519/1 "2007-11-17T22:12:22Z")

</div>

I don’t know how Ruby scoping works when the code involves:

```
nested "def"s
eval
module_eval
instance_eval
define_method

```

It would be nice to find an app-note for this issue. (More generally,  
it would be nice to see written down how ‘self’ and ‘klass’ are used in  
the Ruby execution model.)

It would also be nice to see a history of these meta-programming  
constructs. (I say “meta-programming”, since we’re talking about code  
that executes code.) I wouldn’t be surprised if once upon a time Ruby  
had only nested "def"s and "eval"s. However, I don’t know how to write  
my own version of, say, “attr\_reader” using just those two. For  
example, this doesn’t work:

def my\_attr\_reader name  
eval \<\<-STOP  
def #{name}  
@#{name}  
end  
STOP  
end

I wonder if there is a way. Moving on, the following all work:

def my\_attr\_reader name  
eval \<\<-STOP  
define\_method :#{name} do  
p C # IGNORE FOR NOW  
@#{name}  
end  
STOP  
end

def my\_attr\_reader name  
module\_eval \<\<-STOP  
def #{name}  
p C # IGNORE FOR NOW  
@#{name}  
end  
STOP  
end

def my\_attr\_reader name  
module\_eval \<\<-STOP  
define\_method :#{name} do  
p C # IGNORE FOR NOW  
@#{name}  
end  
STOP  
end

def my\_attr\_reader name # MY FAVORITE, FYI  
define\_method name do  
p C # IGNORE FOR NOW  
instance\_variable\_get “@”+name.to\_s  
end  
end

Alas, There’s More Than One Way To Do It. Now let’s exercise those  
“p C” statements:

module M  
C = “M”

# INSERT ONE OF THE my\_attr\_reader DEFINITIONS HERE

end  
class X  
C = “X”  
class \<\<X ; include M ; end  
attr\_writer :a  
my\_attr\_reader :a  
end  
x = X.new  
x.a = 4  
x.a -\> prints ???

With the four examples above, the printed value of C is:

```
"M" "X" "X" "M"

```

My head is swimming. Ideally, I’ll find my app-note, which will clear  
my mind as marvelously as “How Classes and Objects Interact” did in the  
Pickaxe book.

PS: “@”+name.to\_s is gross. Why doesn’t “instance\_variable\_get” accept  
an _implicit_ “@”?

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [November 17, 2007, 11:20pm UTC](https://www.ruby-forum.com/t/eval-module-eval-define-method-and-all-that/120519/2 "2007-11-17T23:20:13Z")

</div>

I wrote above that my head was swimming. Not enough, evidentally:

If I want my\_attr\_reader to handle multiple attributes, this works:

```
def my_attr_reader *names
  names.each do |name| # THIS IS THE ONLY LINE THAT DIFFERS
    define_method name do
      instance_variable_get "@"+name.to_s
    end
  end
end

```

But this doesn’t:

```
def my_attr_reader *names
  for name in names # THIS IS THE ONLY LINE THAT DIFFERS
    define_method name do
      instance_variable_get "@"+name.to_s
    end
  end
end

```

Ouch.

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [November 18, 2007, 11:59pm UTC](https://www.ruby-forum.com/t/eval-module-eval-define-method-and-all-that/120519/3 "2007-11-18T23:59:36Z")

</div>

My interest (obsession?) with methods defining methods partly derives  
from the fact Ruby got a huge boost (via Rails) because of it.  
Unfortunately, Ruby requires _three_ special behaviors to make it work,  
and these behaviors are provided nonorthogonally. The following fails  
for three reasons. (Please forgive how silly it looks at this point.)

class A  
class \<\<A  
def my\_attr\_reader var # ‘var’ will be bound to :foo.  
def var  
“@”+var.to\_s  
end  
end  
end  
my\_attr\_reader :foo  
attr\_writer :foo  
end

1. In “def foo ; @foo ; end”, “foo” and “@foo” are syntax literals.  
Neither can be replaced with an expression.

2. The inner “def” is installed in \<\<A rather than in A.

3. Ruby tends to scope lexically rather than dynamically. “@foo” is  
likely to be scoped as an instance variable of the A class rather than  
of A instances. Similarly, a referenced constant is likely to be looked  
up in \<\<A rather than A.

Problem #1 can be solved either by evaluating strings or by using  
“define\_method”, “instance\_variable\_get”, and such.

Problem #2 can be solved using “module\_eval” and/or “define\_method”.

Problem #3 is solved (I think) by a combination of “module\_eval” and  
string evaluation.

“module\_eval” with a string argument seems like the best technique from  
an ease-of-use point of view. But string evaluation rubs some people  
the wrong way. On the other hand, “module\_eval” (or “define\_method”)  
with a block argument scopes constants lexically and instance variables  
dynamically:

CONST = “Object”

$block = proc do  
def get\_stuff  
[@foo, CONST, self]  
end  
end

class A  
CONST = “A”  
class \<\<A  
CONST = “\<\<A”  
def def\_get\_stuff  
module\_eval &$block  
end  
end  
attr\_accessor :foo  
def\_get\_stuff  
end

a = A.new  
a.foo = 22  
p a.get\_stuff -\> [22, “Object”, #\<A:0x401c2448 @foo=22\>]

I don’t know if this result is intrinsically messy or if I’m looking at  
it from the wrong angle.

---

<div class="post-metadata">

**Author:** ![S-gw](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@S-gw](https://www.ruby-forum.com/u/S-gw)\
**Post date:** [November 19, 2007, 1:22am UTC](https://www.ruby-forum.com/t/eval-module-eval-define-method-and-all-that/120519/4 "2007-11-19T01:22:10Z")

</div>

In this forum, I’ve mentioned several times that some people don’t like  
“eval”. Here is the end of section 11.3.5 from “The Ruby Way”:

In previous versions of Ruby, we often defined methods at runtime by  
calling “eval”. In essence, “define\_method” can and should be used in  
all these circumstances.

“ALL these circumstances”. That’s strong stuff. Well, I’m ready to bow  
to authority. But how can I see “define\_method” as loveable? How about  
this: “define\_method” is Minimally Magical.

Here’s what I mean. Given the name “define\_method”, we naturally  
expect “foo” and “bar” below to have the same behavior:

CONST = “Object”

class A  
CONST = “A”  
@val = “A”  
attr\_accessor :val  
def foo  
[CONST, @val, self]  
end  
define\_method :bar do  
[CONST, @val, self]  
end  
end

a = A.new  
a.val = “a”  
p a.foo -\> [“A”, “a”, #\<A:0x401c24fc @val=“a”\>]  
p a.bar -\> [“A”, “a”, #\<A:0x401c24fc @val=“a”\>]

If “define\_method” was not magical, then, within its block argument, the  
values of CONST and @val and self would be “A” and “A” and A (the class  
object). The minimal magic required to get the desired answer is to  
make @val and self refer to the A instance, but leave CONST to scope  
lexically. And that seems to be what “define\_method” does.

I personally will follow “The Ruby Way” (second edition). Stand behind  
me, \*eval methods!
