[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

bug in nested defs (?

Greg Weeks

11/11/2007 7:41:00 AM

When the following code is evaluated

def foo ; "foo" ; end

where does the method go? Here is what I would guess.

If the evaluation context of the def is a class, then the method is an
instance method of the class. If the evaluation context of the def is
not a class, then the method is a singleton method of the context
object.

This rule is ugly, but it almost always works. What I don't understand
is the one exception below. Here are the non-exceptions:

class X
def foo ; "foo" ; end # #method of X
end
X.new.foo # works

obj = []
class <<obj
def foo ; "foo" ; end # singleton method of obj
end
obj.foo # works

class Y
def def_foo
def foo ; "foo" ; end # singleton method of Y instances
end
end
y = Y.new
y.def_foo
y.foo # works

class Z
def Z.def_foo
def foo ; "foo" ; end # #method of Z
end
def_foo
end
Z.new.foo # works

And here is the exception:

module Definer
def def_foo
def foo ; "foo" ; end # class method of User !
end
end
class User
extend Definer
def_foo
end
User.foo # works!
User.new.foo # error!

Bug or feature? In particular, why should Z and User give different
results?

PS: All my talk of "execution context" I picked up off the street. I
don't find it discussed in "Programming Ruby" or "The Ruby Way".
--
Posted via http://www.ruby-....

8 Answers

Ryan Davis

11/11/2007 7:51:00 AM

0


On Nov 10, 2007, at 23:40 , Greg Weeks wrote:

> When the following code is evaluated
>
> def foo ; "foo" ; end
>
> where does the method go? Here is what I would guess.
>
> If the evaluation context of the def is a class, then the method is
> an
> instance method of the class. If the evaluation context of the def
> is
> not a class, then the method is a singleton method of the context
> object.

not quite. see "Defining a Method" of the pickaxe ed 2 on page 330.


Greg Weeks

11/11/2007 8:11:00 AM

0

Ryan Davis wrote:
> On Nov 10, 2007, at 23:40 , Greg Weeks wrote:
>
>> not a class, then the method is a singleton method of the context
>> object.
>
> not quite. see "Defining a Method" of the pickaxe ed 2 on page 330.

In my copy, the heading is "Method Definition", and it begins on pg 345.
Are you referring to the paragraph that begins with "Outside a class or
module definition"? That refers to the top-level (I believe). I
omitted that example deliberately since a person who typed it in would
mess up the subsequent examples. Here it is:

def foo ; "foo" ;end
[].foo # works

By the way, I regret my statement that the rule that I stated was ugly.
I thought that I was being self-deprecating about my phrasing of the
rule. But on second thought, neither the phrasing nor the rule is ugly.

However, it doesn't seem to work in the Definer/User example.
--
Posted via http://www.ruby-....

Greg Weeks

11/11/2007 9:01:00 AM

0

Ryan Davis wrote:
> On Nov 10, 2007, at 23:40 , Greg Weeks wrote:
>
>> not a class, then the method is a singleton method of the context
>> object.
>
> not quite. see "Defining a Method" of the pickaxe ed 2 on page 330.

I now see that you're right. The Pick-axe book explains everything:

"A method definition using an unadorned method name within a class
or module definition creates an instance method".

Here, "within" means lexically within, not dynamically within. This
explains my problem case:

module Definer
def def_foo
def foo ; "foo" ; end # class method of User !
end
end
class User
extend Definer
def_foo
end
User.foo # works!
User.new.foo # error!

The def of foo is dynamically within User, but it is lexically within
Definer. (The fact that it is nested doesn't matter.) Consequently,
foo becomes an instance method of Definer.

This also implies (correctly) that the foo method of y is a common
method, not a singleton method. So I was wrong about that too. But I
think I've got it now. Yippee!

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

Phrogz

11/11/2007 4:47:00 PM

0

On Nov 10, 11:40 pm, Greg Weeks <gregwe...@shaw.ca> wrote:
> class Y
> def def_foo
> def foo ; "foo" ; end # singleton method of Y instances
> end
> end
> y = Y.new
> y.def_foo
> y.foo # works

Not a singleton method. It's just a delayed definition of a standard
instance method:

class Bar
def def_foo
def foo
"foo"
end
end
end

b1 = Bar.new
b2 = Bar.new
p b1.foo rescue p "error"
#=> "error"

b1.def_foo
p b1.foo
#=> "foo"

p b2.foo
#=> "foo"


Greg Weeks

11/12/2007 3:15:00 AM

0

After some more thought, the rule that instance methods go into the
lexically enclosing class has surprised me again. Let x = []. I had
thought that the following two methods behaved identically (except for
"foo vs bar", of course):

def x.define_foo
def foo ; "foo" ; end
end

class << x
def define_bar
def bar ; "bar" ;end
end
end

However, in the first case the lexically enclosing class is Object
(well, you know what I mean), and in the second case the lexically
enclosing class is the singleton class of x. So the rule says
(correctly) that the two are different:

x.define_foo
Object.instance_methods.include? "foo" # true
x.singleton_methods.include? "foo" # false

x.define_bar
Object.instance_methods.include? "bar" # false
x.singleton_methods.include? "bar" # true

Good!, I think. But there is still one case where I don't know where
the "def" should go:

x.instance_eval { def baz ; "baz" ; end }

What class acts as the effective enclosing class of the def? Is it
Object, the actual enclosing class? Or Array, the class of x? Or
is it the singleton class of x? The answer is the latter:

x.singleton_methods.include? "baz" # true

Whew!

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

Greg Weeks

11/12/2007 8:20:00 AM

0

BTW, as I now understand it, I grabbed the wrong end of the stick when I
concerned myself with nested defs. I'm pretty sure that no good program
does this, not for an inner instance method anyway. "define_method" is
always preferable. (Counterexample, anyone?) In that case, a practical
response to the question of how nested defs behave is to not care. I
*think* that that is the right response. As a newcomer, though, I can't
say for sure.

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

Ryan Davis

11/12/2007 10:07:00 AM

0


On Nov 11, 2007, at 08:50 , Phrogz wrote:

> Not a singleton method. It's just a delayed definition of a standard
> instance method:
>
> class Bar
> def def_foo
> def foo
> "foo"
> end
> end
> end

It actually looks pretty cool:

% parse_tree_show -u
# ...
^D
s(:class,
:Bar,
nil,
s(:scope,
s(:defn,
:def_foo,
s(:args),
s(:scope,
s(:block,
s(:defn, :foo, s(:args), s(:scope, s(:block, s(:str,
"foo")))))))))

So the defn foo is just sitting inside. Whenever def_foo gets
executed, the defn inside gets interpreted, defining the new foo in
whatever context it is executing in.


Ubiquitous

10/27/2013 11:03:00 PM

0

et472@ncf.ca wrote:
>On Sun, 27 Oct 2013, Ubiquitous wrote:
>> dimlan17@yahoo.com wrote:

>>> 'Simpsons' showrunner Al Jean to retire Marcia Wallace's character,
>>
>> I thought Edna Krabappel had already retitred. I distinctly remember
>> catching part of a recent ep in which Bart persuaded her to put her
>> retirement on hold to help him take care of some problem at the school.
>
>I don't remember that (but I miss The Simpsons when The Amazing Race is on),

Yeah, I don't pay attention when it's on, but she helped Bart get rid of
someone at the school (or maybe get Skinner's job back).


--
Q: Why is ObamaCare like a turd?
A: You have to pass it to see what's in it.