Define method and def


M

Minkoo Seo

Hi group.

This is a question on metaprogramming in Ruby.

What's the difference between define_method:)symbol) and defining a
class using def ..;end? As an example,

irb(main):001:0> class Foo; end
=> nil
irb(main):002:0> Foo.instance_eval do
irb(main):003:1* define_method:)bar) do
irb(main):004:2* puts "bar"
irb(main):005:2> end
irb(main):006:1> end
=> #<Proc:[email protected](irb):3>
irb(main):007:0> Foo.bar
NoMethodError: undefined method `bar' for Foo:Class
from (irb):7
irb(main):008:0> Foo.new.bar
bar
=> nil
irb(main):009:0> Foo.instance_eval do
irb(main):010:1* def baz
irb(main):011:2> puts "baz"
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> Foo.baz
baz
=> nil
irb(main):015:0> f.baz
NameError: undefined local variable or method `f' for main:Object
from (irb):15

Foo is an instance of Class. Therefore, defining methods taking Foo as
an instance (of Class) must introduce class method. Right? But the
above example shows that it also depends on whether define_method is
called or def is used.

What's difference? Why does Foo.bar is not defined when I use
define_method?

Sincerely,
Minkoo Seo
 
Ad

Advertisements

T

ts

M> Foo is an instance of Class. Therefore, defining methods taking Foo as
M> an instance (of Class) must introduce class method. Right? But the

no. #define_method is a Module private method : Foo.define_method
introduce an instance method.

M> above example shows that it also depends on whether define_method is
M> called or def is used.

#instance_eval is executed with self = Foo and default_class = Foo
singleton class. In this case `def' introduce a singleton method (it use the
default class)

#class_eval is executed with self = default_class = Foo and `def'
introduce an instance method.
 
R

ralf

Hi,
in PickAxe2, p.555: define_method :"Defines an instance method in the
receiver "
the reveiver is the class Foo. bar should (imo) be a instance method of
the class Foo.
instance_eval (p.571): "Evaluates the block in the context of the
receiver". receiver is class Foo , but what means "in the context"? If
it differs from "in the receiver" is could be a class method. Well,
just guessing...

The "in the context of the receiver" and "in the receiver" is a bit
confusing, at least for me as non-native english speaker. Hopefully the
term "in context" has this meaning. But your example makes clear the
difference (if I'm right).

regards
Ralf
 
M

Minkoo Seo

ts said:
#instance_eval is executed with self = Foo and default_class = Foo
singleton class. In this case `def' introduce a singleton method (it use the
default class)

#class_eval is executed with self = default_class = Foo and `def'
introduce an instance method.

Thanks ts. But, could you tell me what 'default_class' is? This is the
first time for me to see the term.

And I got another question. Isn't the self is Foo singleton class in
the following?

Foo.instance_eval do
# self = Foo singletone class
end
 
T

ts

M> Thanks ts. But, could you tell me what 'default_class' is? This is the
M> first time for me to see the term.

because I'm alone to use it :) don't forget that I'm stupid.

When ruby call `def' it will use an "internal" variable ruby_class which
will give it where the method must be defined.

For example, at top level it has self = main, ruby_class = Object : the
method will be an object method.

With Foo.instance_method it has self = Foo, ruby_class = Foo
singleton class (#<Class:Foo>) : the method will be a Foo singleton method.

M> Foo.instance_eval do
M> # self = Foo singletone class
M> end

no, no : self is Foo in this case

moulon% ruby -e 'module Foo end; Foo.instance_eval { p self }'
Foo
moulon%

Foo singleton class is

moulon% ruby -e 'module Foo end; p class << Foo; self end'
#<Class:Foo>
moulon%
 
M

Minkoo Seo

ts said:
With Foo.instance_method it has self = Foo, ruby_class = Foo
singleton class (#<Class:Foo>) : the method will be a Foo singleton method.

Well, then does it mean that when I use "def", the method defined is
geneated somewhere different from 'self'?
moulon% ruby -e 'module Foo end; Foo.instance_eval { p self }'
Foo
moulon%

In this case,

Foo.instance_eval do
def bar
end
end

defines 'bar' at Foo singletone class while self, which I have been
thought to be the receiver of def keyword, is Foo. Right? Then, how do
you know where the method defined by 'def' is generated in general?

Frankly, I've been trying to memorize how to geneate 'instance/class'
method and want to find some rules for metaprogramming.

- Minkoo
 
Ad

Advertisements

T

ts

M> Well, then does it mean that when I use "def", the method defined is
M> geneated somewhere different from 'self'?

yes,

there is no relation between self and `def', because for `def' ruby use
ruby_class (an internal variable).

M> defines 'bar' at Foo singletone class while self, which I have been
M> thought to be the receiver of def keyword, is Foo. Right?

Well, see it like this

a = []
a.instance_eval {
p self
def bar
end
}

Where do you want that ruby define the method ?
 
Ad

Advertisements

G

George Ogata

Minkoo Seo said:
In this case,

Foo.instance_eval do
def bar
end
end

defines 'bar' at Foo singletone class while self, which I have been
thought to be the receiver of def keyword, is Foo. Right? Then, how do
you know where the method defined by 'def' is generated in general?

Frankly, I've been trying to memorize how to geneate 'instance/class'
method and want to find some rules for metaprogramming.


I trekked the source the other day to clear this up in my mind, so
I'll offer another explanation, in case anyone's interested.

At any point in any ruby code, ruby has a concept of the "current
object", which is what is referenced by `self', and the "current
class", which is the class that gets a new instance method when you do
`def ... end'. They are orthogonal concepts.

* Inside a class (`class Foo ... end'), the "current object" is Foo,
and the "current class" is also Foo. Hence, `self' refers to the
class, and doing `def ... end' adds to the class.

* At the toplevel, the "current object" is an instance of Object, and
the "current class" is Object. This explains why, at the toplevel,
methods you define become instance methods of Object, but `self' is
NOT the Object class:

irb(main):001:0> self
=> main
irb(main):002:0> self.class
=> Object

If self were the Object class, line 001 would print "Object" and
line 002 would print "Class". So to anyone that says "imagine the
toplevel is wrapped in `class Object; private; ... end'", you're
wrong!

* When you call `foo.instance_eval', the "current object" is set to
`foo', and the "current class" is set to foo's singleton class, then
the block is yielded / string is evalled. Thus, `self' refers to
`foo', while `def ... end' adds to foo's singleton class.

* When you call `Foo.class_eval', the "current object" is set to
`Foo', and the "current class" is set to `Foo', then the block is
yielded / string is evalled. This is just like inside a `class
... end' expression.

I think that's it. Hope it helps.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top