Proposal: class<<obj to invoke extend_object

‘obj.extend’ and ‘class<<obj’ are close cousins…
However there is a difference… ‘class<<obj’ doesn’t
invoke #extend_object, and #extended. To me it feels
inconsistent that there is no way to execute code on the
point when the extension occurs.

I propose that ‘class<<obj’ invokes #extend_object and #extended.

Lets make a comparison… first I present some code
which works using #extend.
Next I present some code which doesn’t work… but
which should work.

ruby a.rb
hello
cat a.rb
module M
def self.extended(parent)
parent.init_m
end
def init_m
@str = “hello”
end
def hello
puts @str
end
end
class C
end
c = C.new
c.extend(M)
c.hello

The next part doesn’t work… (thus the proposal)

cat b.rb
class C
end
c = C.new

class << c
def self.extended(parent) # proposal: invoke me :wink:
parent.init_m
end
def init_m
@str = “hello”
end
def hello
puts @str
end
end

c.hello

ruby b.rb
b.rb:13: warning: instance variable @str not initialized
nil

···


Simon Strandgaard

Hi,

···

In message “proposal: class<<obj to invoke extend_object” on 04/03/08, Simon Strandgaard neoneye@adslhome.dk writes:

‘obj.extend’ and ‘class<<obj’ are close cousins…
However there is a difference… ‘class<<obj’ doesn’t
invoke #extend_object, and #extended. To me it feels
inconsistent that there is no way to execute code on the
point when the extension occurs.

‘obj.extend’ add a module to the inheritance graph (per object base),
whereas ‘class <<obj’ add methods and attributes to the existing
singleton class. Virtually, singleton class always exists for each
object, never added, never extended.

						matz.

I don’t get this… (thanks+sorry matz).

I had the impression that they didn’t differ much.
Is there anyone which can explain this to me?

Thanks in advance

···

On Mon, 08 Mar 2004 08:35:34 +0900, Yukihiro Matsumoto wrote:

In message “proposal: class<<obj to invoke extend_object” > on 04/03/08, Simon Strandgaard neoneye@adslhome.dk writes:

‘obj.extend’ and ‘class<<obj’ are close cousins…
However there is a difference… ‘class<<obj’ doesn’t
invoke #extend_object, and #extended. To me it feels
inconsistent that there is no way to execute code on the
point when the extension occurs.

‘obj.extend’ add a module to the inheritance graph (per object base),
whereas ‘class <<obj’ add methods and attributes to the existing
singleton class. Virtually, singleton class always exists for each
object, never added, never extended.


Simon Strandgaard

Hi –

(Testing a new way of posting to Usenet… hoping it works…)
(Copy to Simon)

‘obj.extend’ and ‘class<<obj’ are close cousins…
However there is a difference… ‘class<<obj’ doesn’t
invoke #extend_object, and #extended. To me it feels
inconsistent that there is no way to execute code on the
point when the extension occurs.

‘obj.extend’ add a module to the inheritance graph (per object base),
whereas ‘class <<obj’ add methods and attributes to the existing
singleton class. Virtually, singleton class always exists for each
object, never added, never extended.

I don’t get this… (thanks+sorry matz).

I had the impression that they didn’t differ much.
Is there anyone which can explain this to me?

When you do “obj.extend(Mod)”, obj.ancestors changes (new module
added).

When you do “class << obj … end”, obj.ancestors stays the same. All
you’re doing is adding a method to a class; you’re not extending obj,
in the sense of putting a new module in its ancestry (i.e., method
lookup path).

If you invoked #extended every time you did this, you’d have to invoke
it on every String object if you did:

class String
#…
end

Singleton classes are, I think, implemented in such a way that they
don’t actually have existence until they’re first referred to. But,
as Matz says, every object virtually has a singleton class all the
time.

David

···

On Mon, 8 Mar 2004, Simon Strandgaard wrote:

On Mon, 08 Mar 2004 08:35:34 +0900, Yukihiro Matsumoto wrote:

In message “proposal: class<<obj to invoke extend_object” > > on 04/03/08, Simon Strandgaard neoneye@adslhome.dk writes:


David A. Black
dblack@wobblini.net

David A. Black wrote:

I had the impression that they didn’t differ much.
Is there anyone which can explain this to me?

When you do “obj.extend(Mod)”, obj.ancestors changes (new module
added).

To be precise, class << obj; self end.ancestors changes :slight_smile:

/kent

David A. Black wrote:

I had the impression that they didn’t differ much.
Is there anyone which can explain this to me?

When you do “obj.extend(Mod)”, obj.ancestors changes (new module
added).

To be precise, class << obj; self end.ancestors changes :slight_smile:

Thanks David and Kent, now I understand. it seems logical that the
ancestors change when doing ‘obj.extend’, and doesn’t when doing
‘class<<obj’.

Still… I propose that ‘class<<self’ should invoke #extended or some sort
of suitable replacement, so that initialization can take place.
What do you think ?

Should it be named #extended ? or have another name?

ATT: David A Black

(Testing a new way of posting to Usenet… hoping it works…)
(Copy to Simon)

Your message didn’t show up in the newsgroup… But the posting which I am
replying to now gave me a hint, so I checked on ruby-talk, and saw your
message there.

···

On Sun, 07 Mar 2004 19:59:50 -0500, Kent S. wrote:


Simon Strandgaard

Hi --

> David A. Black wrote:
>>>I had the impression that they didn't differ much.
>>>Is there anyone which can explain this to me?
>>
>>
>> When you do "obj.extend(Mod)", obj.ancestors changes (new module
>> added).
>>
>
> To be precise, class << obj; self end.ancestors changes :slight_smile:
>

Thanks David and Kent, now I understand. it seems logical that the
ancestors change when doing 'obj.extend', and doesn't when doing
'class<<obj'.

Still... I propose that 'class<<self' should invoke #extended or some sort
of suitable replacement, so that initialization can take place.
What do you think ?

Should it be named #extended ? or have another name?

I don't think there needs to be such a thing. (If there is, it
definitely shouldn't have the word "extend" in it, since that could
cause confusion with the current concept of extending an object, as
described wrongly by me and correctly by Kent.) As Nobu pointed out
in another thread, you can just do:

  class << obj
    puts "Executing a puts statement...."
    # ...
  end

and the code will execute.

ATT: David A Black
> (Testing a new way of posting to Usenet.... hoping it works....)
> (Copy to Simon)
>

Your message didn't show up in the newsgroup... But the posting which I am
replying to now gave me a hint, so I checked on ruby-talk, and saw your
message there.

Thanks :slight_smile: My Usenet provider seems to propagate things very slowly,
especially on weekends, so it's possible it will show up later.

David

···

On Mon, 8 Mar 2004, Simon Strandgaard wrote:

On Sun, 07 Mar 2004 19:59:50 -0500, Kent S. wrote:

--
David A. Black
dblack@wobblini.net

Hi,

···

In message “Re: proposal: class<<obj to invoke extend_object” on 04/03/08, Simon Strandgaard neoneye@adslhome.dk writes:

Still… I propose that ‘class<<self’ should invoke #extended or some sort
of suitable replacement, so that initialization can take place.
What do you think ?

Should it be named #extended ? or have another name?

Describe yourself deeper. What exactly is your proposal? And why do
you think it’s needed?

Remember, since singleton class always exists for each object
(virtually), ‘class <<obj’ is rather corresponds to class re-opening.

						matz.

David A. Black wrote:

Simon Strandgaard wrote:

Still… I propose that ‘class<<self’ should invoke #extended or some sort
of suitable replacement, so that initialization can take place.
What do you think ?

Should it be named #extended ? or have another name?

I don’t think there needs to be such a thing. (If there is, it
definitely shouldn’t have the word “extend” in it, since that could
cause confusion with the current concept of extending an object, as
described wrongly by me and correctly by Kent.) As Nobu pointed out
in another thread, you can just do:

class << obj
puts “Executing a puts statement…”

end

and the code will execute.

Sorry… this doesn’t work in the following example.
I have tried with instance_eval, but no luck either.

ruby a.rb
a.rb:9: undefined local variable or method `init’ for #<Class:#String:0x810aa08> (NameError)
expand -t2 a.rb
obj = “text”
class << obj
def init
@str = “hello”
end
def hello
puts @str
end
init
end
obj.hello

···


Simon Strandgaard

Still… I propose that ‘class<<self’ should invoke #extended or some sort
of suitable replacement, so that initialization can take place.
What do you think ?

Should it be named #extended ? or have another name?

Describe yourself deeper. What exactly is your proposal?

When ‘class<<obj’ is seen by Ruby, then an init method should be invoked.
I propose to reuse #extend_object and #extended for this.

And why do you think it’s needed?

Its difficult to add an new instance variable to obj.
Its inflexible compared to obj.extend(Mod), because there isn’t
invoked an #extend_object method when the extension occurs.

An alternative to what I propose may be to do something
ala (warning pseudo code)… which isn’t intuitive…

class << obj
def singleton_method_added(parent)
if first time we got invoked
@str = “hello”
end
end
end

Remember, since singleton class always exists for each object
(virtually), ‘class <<obj’ is rather corresponds to class re-opening.

I am only little familiar with class re-opening…

···

On Mon, 08 Mar 2004 11:18:42 +0900, Yukihiro Matsumoto wrote:

In message “Re: proposal: class<<obj to invoke extend_object” > on 04/03/08, Simon Strandgaard neoneye@adslhome.dk writes:


Simon Strandgaard

[Simon Strandgaard neoneye@adslhome.dk, 2004-03-08 04.24 CET]
[…]

Sorry… this doesn’t work in the following example.
I have tried with instance_eval, but no luck either.

ruby a.rb
a.rb:9: undefined local variable or method `init’ for #<Class:#String:0x810aa08> (NameError)
expand -t2 a.rb
obj = “text”
class << obj
def init
@str = “hello”
end
def hello
puts @str
end
init
end
obj.hello

Maybe you should ask for a method #singleton for singleton classes,
that returns the object… :wink:

Simon Strandgaard wrote:

Remember, since singleton class always exists for each object
(virtually), ‘class <<obj’ is rather corresponds to class re-opening.

I am only little familiar with class re-opening…

‘class << obj’ by itself simple changes the current scope to the
instance’s singleton class. It doesn’t change neither the instance
itself, nor its inheritance structure. So I don’t think this action
should be reflected by any callback action.

/kent

Hi,

Describe yourself deeper. What exactly is your proposal?

When ‘class<<obj’ is seen by Ruby, then an init method should be invoked.
I propose to reuse #extend_object and #extended for this.

And why do you think it’s needed?

Its difficult to add an new instance variable to obj.
Its inflexible compared to obj.extend(Mod), because there isn’t
invoked an #extend_object method when the extension occurs.

You didn’t explain why you need “extended” for singleton class
definition. Why don’t you use extend for your purpose, before
changing the language?

Remember, since singleton class always exists for each object
(virtually), ‘class <<obj’ is rather corresponds to class re-opening.

I am only little familiar with class re-opening…

I want you to take a break and learn about Ruby before claiming apples
and oranges are similar. Yes, they are. But not the same. Besides
that, singleton class definition is a kind of class re-opening, so
that they should remain same.

Class re-opening is a class definition whose target is an existing
class, for example:

class String
def foo # String#foo become available
end
end

there’s no hook for class re-opening.

						matz.
···

In message “Re: proposal: class<<obj to invoke extend_object” on 04/03/08, Simon Strandgaard neoneye@adslhome.dk writes:

[snip]

Maybe you should ask for a method #singleton for singleton classes,
that returns the object… :wink:

I tried poking around with ‘singleton’… but no luck.
Please give me some more hints.

:wink:

ruby a.rb
#<Class:#String:0x810a9b8>
a.rb:7: warning: instance variable @str not initialized
nil
cat a.rb
obj = “text”
class << obj
def init
@str = “hello”
end
def hello
puts @str
end
p self
#p self.methods
#p self.singleton_methods
end
obj.hello

···

On Tue, 09 Mar 2004 00:02:13 +0900, Carlos wrote:


Simon Strandgaard

Describe yourself deeper. What exactly is your proposal?

When ‘class<<obj’ is seen by Ruby, then an init method should be invoked.
I propose to reuse #extend_object and #extended for this.

And why do you think it’s needed?

Its difficult to add an new instance variable to obj.
Its inflexible compared to obj.extend(Mod), because there isn’t
invoked an #extend_object method when the extension occurs.

You didn’t explain why you need “extended” for singleton class
definition. Why don’t you use extend for your purpose, before
changing the language?

I don’t have a serious need for ‘class<<obj’.

I have recently initiated working on a book about testing, with a few
chapters about Ruby. My first attempt of making an good example of how
to use the ‘class<<obj’, I discovered that no init method got invoked.
Thus I got curious to if that was a missing feature.

My initial thought were first to describe ‘obj.extend(Mod)’ and next
describe ‘class<<obj’ as being similar, but this isn’t true.
So its probably better to describe them in separate.

Remember, since singleton class always exists for each object
(virtually), ‘class <<obj’ is rather corresponds to class re-opening.

I am only little familiar with class re-opening…

I want you to take a break and learn about Ruby before claiming apples
and oranges are similar. Yes, they are. But not the same. Besides
that, singleton class definition is a kind of class re-opening, so
that they should remain same.

Ok, I am learning every day :wink:

Class re-opening is a class definition whose target is an existing
class, for example:

class String
def foo # String#foo become available
end
end

there’s no hook for class re-opening.

I wasn’t sure about what kind of reopening you talked about in last mail.
Yes, I have used this a few times. However I am only interested in
modifying a specific instance with ‘class<<obj’.

Sorry for todays noise. :wink:

···

On Mon, 08 Mar 2004 12:58:45 +0900, Yukihiro Matsumoto wrote:

on 04/03/08, Simon Strandgaard <neoneye@adslhome.dk> writes:


Simon Strandgaard

Hi --

[snip]
> Maybe you should ask for a method #singleton for singleton classes,
> that returns the object... :wink:

I tried poking around with 'singleton'.. but no luck.
Please give me some more hints.

:wink:

> ruby a.rb
#<Class:#<String:0x810a9b8>>
a.rb:7: warning: instance variable @str not initialized
nil
> cat a.rb
obj = "text"
class << obj
  def init
    @str = "hello"
  end
  def hello
    puts @str
  end
  p self
  #p self.methods
  #p self.singleton_methods
end
obj.hello

Here's something which might suggest some possibilities for the kind
of thing you want to do. It shows a way to keep both an object and
its singleton class in scope:

  obj = Object.new

  c = (class << obj; self; end)

  c.class_eval do
    define_method("x") do
      puts "I am an object: #{self}"
      puts "I'm assigned to the variable obj: #{obj}"
      puts "My singleton class is a class: #{c}"
      puts "My historical class is also a class: #{self.class}"
    end
  end

  obj.x

  =>
    I am an object: #<Object:0x401b8d40>
    I'm assigned to the variable obj: #<Object:0x401b8d40>
    My singleton class is a class: #<Class:#<Object:0x401b8d40>>
    My historical class is also a class: Object

David

···

On Tue, 9 Mar 2004, Simon Strandgaard wrote:

On Tue, 09 Mar 2004 00:02:13 +0900, Carlos wrote:

--
David A. Black
dblack@wobblini.net

[Simon Strandgaard neoneye@adslhome.dk, 2004-03-08 16.19 CET]

[snip]

Maybe you should ask for a method #singleton for singleton classes,
that returns the object… :wink:

I tried poking around with ‘singleton’… but no luck.
Please give me some more hints.

No… it doesn’t exist (as I know), but if it existed, you could
do what you are trying to do with

class << obj
def init

end

singleton.init
end

This is why I said that maybe you should ask for it (to Matz). Sorry
for false expectations…

···

On Tue, 09 Mar 2004 00:02:13 +0900, Carlos wrote:

Hi --

I wasn't sure about what kind of reopening you talked about in last mail.
Yes, I have used this a few times. However I am only interested in
modifying a specific instance with 'class<<obj'.

Here's another way to look at all of this.

You're right that extending an object is in the same family of
operations, so to speak, as defining methods in that object's
singleton class. However, within that family (things that affect what
messages the object responds to, and/or how it responds to them),
those two things are in a sense the opposite of each other.

The methods added to an object's capabilities by obj.extend(Mod) are,
typically, methods which also get added to other objects (since that
what modules are good at). Therefore, extending an object tends to
move it in the direction of having more in common with other objects
-- for example, enumerability.

Defining a method in an object's singleton class, however, whether one
does it like this:

  def obj.meth ...

or like this:

  class << obj
    def meth ...

is the opposite: it represents a decision to increase the difference
between obj and other objects.

So, in addition to the consistency Matz was talking about (keeping all
class reopenings the same), I think there's also this difference in
role or intention that actually makes singleton methods rather
un-extend-like.

David

···

On Mon, 8 Mar 2004, Simon Strandgaard wrote:

--
David A. Black
dblack@wobblini.net

Hi –

[Simon Strandgaard neoneye@adslhome.dk, 2004-03-08 16.19 CET]

[snip]

Maybe you should ask for a method #singleton for singleton classes,
that returns the object… :wink:

I tried poking around with ‘singleton’… but no luck.
Please give me some more hints.

No… it doesn’t exist (as I know), but if it existed, you could
do what you are trying to do with

class << obj
def init

end

singleton.init
end

This is why I said that maybe you should ask for it (to Matz). Sorry
for false expectations…

Here’s a brute-force but perhaps useable implementation:

class Class
def single_instance
ObjectSpace.each_object do |obj|
c = (class << obj; self; end)
return obj if c == self
end
end
end

p (class << “hello”; self; end).single_instance # “hello”

David

···

On Tue, 9 Mar 2004, Carlos wrote:

On Tue, 09 Mar 2004 00:02:13 +0900, Carlos wrote:


David A. Black
dblack@wobblini.net

Carlos wrote:

I tried poking around with ‘singleton’… but no luck.
Please give me some more hints.

No… it doesn’t exist (as I know), but if it existed, you could
do what you are trying to do with

class << obj
def init

end

singleton.init
end

This is why I said that maybe you should ask for it (to Matz). Sorry
for false expectations…

I don’t understand this. What should singleton method/attribute return?
As I understand this correctly, init method in this case is a
instance’s method, not a singleton class’s method.

/kent