Singleton method on object via define_method?

R

Randy W. Sims

gabriele said:
Randy W. Sims ha scritto:
Sounds sort of like a traits[1] or what Perl 6 refers to as
roles[2][3]. But, then this is deeper Ruby than I'm familiar with.


I think traits mostly are what we call modules

I'm still learning Ruby, but aren't modules pretty much static? I think
of traits as a set of behaviors that an object can take on at any point
in it's lifetime. These behaviors are specific to that instance. They
are transient behaviors that can be taken on and latter shed off. You
would test for the presence of a trait before using it (much like
testing is_a?). etc.

Randy.
 
P

Phil Tomson

gabriele said:
Randy W. Sims ha scritto:
Sounds sort of like a traits[1] or what Perl 6 refers to as
roles[2][3]. But, then this is deeper Ruby than I'm familiar with.


I think traits mostly are what we call modules

I'm still learning Ruby, but aren't modules pretty much static? I think
of traits as a set of behaviors that an object can take on at any point
in it's lifetime. These behaviors are specific to that instance. They
are transient behaviors that can be taken on and latter shed off. You
would test for the presence of a trait before using it (much like
testing is_a?). etc.

You can always add more methods to a module as well as remove methods from
a module:

irb(main):001:0> module Foo
irb(main):002:1> def a
irb(main):003:2> "a"
irb(main):004:2> end
irb(main):005:1> def b
irb(main):006:2> "b"
irb(main):007:2> end
irb(main):008:1> end
=> nil
irb(main):009:0> class Bar
irb(main):010:1> include Foo
irb(main):011:1> end
=> Bar
irb(main):012:0> b = Bar.new
=> #<Bar:0x400c3418>
irb(main):013:0> b.a
=> "a"
irb(main):014:0> b.b
=> "b"
irb(main):015:0> module Foo
irb(main):016:1> undef b
irb(main):017:1> end
irb(main):018:0> b.b
NoMethodError: undefined method `b' for #<Bar:0x400c3418>
from (irb):18
irb(main):019:0>
irb(main):019:0> module Foo
irb(main):020:1> def c
irb(main):021:2> "c"
irb(main):022:2> end
irb(main):023:1> end
=> nil
irb(main):024:0> b.c
=> "c"

However, with traits & roles (and I'm certainly no expert) wouldn't it be
better to have different modules that get mixed-in and 'unmixed'.

So you might have:

class Baz
end

baz = Baz.new
baz.extend Foo #baz now has Foo 'traits'

....and later you might want to do:
baz.unextend Foo #remove the Foo 'traits' from baz

....later on you could add another set of traits to baz:
baz.extend OtherTraits

Of course there is no 'unextend', but there are probably ways to
implement this. For example, you could get a list of all of the methods
of Foo and undef them in the baz object (couldn't you?)

Phil
 
G

Gavin Sinclair

Phil said:
So you might have:

class Baz
end

baz = Baz.new
baz.extend Foo #baz now has Foo 'traits'

....and later you might want to do:
baz.unextend Foo #remove the Foo 'traits' from baz

....later on you could add another set of traits to baz:
baz.extend OtherTraits

Of course there is no 'unextend', but there are probably ways to
implement this. For example, you could get a list of all of the methods
of Foo and undef them in the baz object (couldn't you?)

I'd expect a proper implementation of 'unextend' to just "peel away a
layer of methods", not actually remove them. So...

module Foo1
def foo; "foo1"; end
end

module Foo2
def foo; "foo2"; end
end

class X
end

x = X.new

x.foo # error

x.extend Foo1
x.foo # "foo1"

x.extend Foo2
x.foo # "foo2"

x.unextend Foo2
x.foo # "foo1"

Gavin
 
P

Phil Tomson

I'd expect a proper implementation of 'unextend' to just "peel away a
layer of methods", not actually remove them. So...

module Foo1
def foo; "foo1"; end
end

module Foo2
def foo; "foo2"; end
end

class X
end

x = X.new

x.foo # error

x.extend Foo1
x.foo # "foo1"

x.extend Foo2
x.foo # "foo2"

x.unextend Foo2
x.foo # "foo1"

Yes, you're right. This would be better behavior. Any idea how something
like that could be implemented?

Phil
 
P

Phil Tomson

Hi --



Actually if C++ has virtual classes, I think that's all the more
reason for Ruby not to call them that. Any such point of contact
inevitably leads to misunderstanding and/or expectation (i.e., that
Ruby will be like the other language).

I agree. There are already too many overloaded terms - isn't that why we
were trying to get away from using 'singleton' class?

Now I don't remember, but what was the problem with calling them
metaclasses?

Phil
 
G

Gavin Sinclair

Phil said:
Yes, you're right. This would be better behavior. Any idea how
something like that could be implemented?

Yep: in the Ruby core! :)

Only pure-Ruby solution I can think of is to remember the modules that
have been mixed in, and selectively reapply earlier ones when 'unextend'
is called. Pretty fugly.

Gavin
 
Z

Zach Dennis

I've got a dummy site up and working with Arrow, but I have a
question....In the httpd.conf file you specify something like:

RubyAddPath /usr/local/lib/ruby/site_ruby/1.8
RubyRequire arrow
<Location /camphq>
SetHandler ruby-object
RubyHandler "Arrow::Dispatcher::instance(
'/var/www/camphq/config/camphq.cfg' )"
</Location>

Where /camphq is how the url of how you want to access your site. IE:
http://mysite.com/camphq . However in my Arrow config file you have
something like:

applets:
defaultApplet: "/index" #Note this line
missingApplet: "/missing"
errorApplet: "/error"
pattern: "*.rb"
path:
- "/var/www/camphq/applets"
pollInterval: 5
config: {}
layout:
"/index": Index # Note this line to

You would think that if you went to http://mysite.com/camphq/index it
would run the defaultApplet "/index" (which actually tells the layout
"/index" to run ). But it doesn't! Instead you have to say:

applets:
defaultApplet: "/camphq/index" #Note this line
missingApplet: "/missing"
errorApplet: "/error"
pattern: "*.rb"
path:
- "/var/www/camphq/applets"
pollInterval: 5
config: {}
layout:
"/camphq/index": Index # Note this line to

in order for the url to work (http://mysite.com/camphq/index ). Is there
a way around this. I would like to assume that the URL root specified in
the httpd.conf file was the root of my Arrow-based "Portal" (can i call
it that?) Thanks!!

Zach
 
T

trans. (T. Onoma)

I agree. There are already too many overloaded terms - isn't that why we
were trying to get away from using 'singleton' class?

Now I don't remember, but what was the problem with calling them
metaclasses?

Cause it is so meta-meaningless !?

What about something most meaningful, like per_instance_class or
per_object_class. Albeit virtual_class doesn't bother me as much. I don't C.

--
( o _ カラãƒ
// trans.
/ \ (e-mail address removed)

I don't give a damn for a man that can only spell a word one way.
-Mark Twain
 
P

Phil Tomson

Yep: in the Ruby core! :)

Yeah, I'm afraid you're probably right (at least to do it 'nicely')
Only pure-Ruby solution I can think of is to remember the modules that
have been mixed in, and selectively reapply earlier ones when 'unextend'
is called. Pretty fugly.

Perhaps, but it's probably possible. Is there an 'extended' callback? if not
'extend' could be redefined.

Phil
 
G

Gavin Sinclair

Phil said:
Perhaps, but it's probably possible. Is there an 'extended' callback?
if not 'extend' could be redefined.

The callback you're after is Module#append_features, from memory. On
first thought, I doubt that's useful, because it's from each individual
module's POV.

If I were implementing this, I'd create new methods rather than modify
#entend, at least at first. Something like:

Object#wrap(module)
Object#unwrap(module)

Perhaps a traits lit. review would turn up some agreeable terminology.

Cheers,
Gavin
 
R

Robert Klemme

David A. Black said:
Hi --

Originally I was going to argue that "virtual" is inappropriate because it
was deceiving. While thinking about this issue it occurred to me that
"singleton classes" aka "virtual classes" share a property with C++'s
"virtual classes": you cannot instantiate objects from them.

Actually if C++ has virtual classes, I think that's all the more
reason for Ruby not to call them that. Any such point of contact
inevitably leads to misunderstanding and/or expectation (i.e., that
Ruby will be like the other language).

OTOH, you can have exactly one instance of this class, but this instance
preceedes the class (i.e. first the instance is created and then - maybe -
the class). Strictly speaking, the instance is the factory for the
class - not the other way round as it is normally.

<philosophical>I depends on everyones notion of "class" whether he or she
thinks this no longer makes it a class. Although in that case I'd be
interested to learn a more appropriate name for this
thing. said:
[I wrote:]

the whole per-object
behavior model of Ruby is based on the idea that every object has both
a class of origin and a class of its own where the definitions
exclusive to that object reside. This isn't abnormal, nor an
aberration; it's the way the whole thing works.

Well, it's normal in Ruby. But generally speaking the naive OO expert
would expect either not to have singleton/virtual classes (SVC :)) *or*
have Object#class return the singleton class - if that would exist. Note,
I'm not advocating to change this in any way - in fact it's good the way
it is. I just try to uncover why SVC often create confusion.

"Naive OO expert" -- interesting :)

Isn't it? :)
"Normal in Ruby" is good enough
for me, since we're talking about Ruby. Otherwise it becomes an
argument that there's an immutable/official OO model that languages
must not deviate from. (I know you don't really think this -- I'm
just extrapolating from what you're saying.)

Well, yes, the extrapolation was correct. Although I couldn't agree more,
that there is no such thing as a commonly agreed model of OO, I'd say
singleton classes the way they are in Ruby are not part of it. :)
I think we're looking at this backwards in this discussion. We're
looking at it as: Objects have this weird class-like thing, so what
is it? I think it's better to look at it from the other end, like
this: Objects in Ruby can have methods added to them on a per-object
basis. That's a fundamental principle of Ruby (whether it is true of
other OO languages or not). The way Matz has chosen to implement this
is by associating a second, dedicated class with each object. That's
what this class actually *is* -- it's the fulfillment of that design,
not something growing off the design that has to be explained
separately.

While that's certainly true, we're (I am) here trying to grasp the nature
of these things to come up with a more appropriate name. At least that's
my understanding of the thread.
The details then fall into place. The fact that the class doesn't
exist until it's needn't does not have to mean that there's anything
virtual about it

.... but it might be a good reason to call it "virtual": it simply doesn't
exist the whole time. :) OTOH, you can't tell from the outside - it's
there when you need it - lazyly initialized... ("lazy_class"? Oh no...)
-- it's just a matter of efficiency, and it's
transparent. And it's a perfectly real class, because it fits the
definition of what a class can be in Ruby.

.... apart from the instance creation.
Hmmm... "dedicated_class"... hmmm... :)

How about "instance_class"?

Hmm...

robert
 
M

Mauricio Fernández

.... but it might be a good reason to call it "virtual": it simply doesn't
exist the whole time. :) OTOH, you can't tell from the outside - it's
there when you need it - lazyly initialized... ("lazy_class"? Oh no...)

There's at least one case where you can know if the singleton class has
been created or not (singletons of singletons). And you can always know
if you're using evil.rb, of course :)
 
G

gabriele renzi

Phil Tomson ha scritto:
I agree. There are already too many overloaded terms - isn't that why we
were trying to get away from using 'singleton' class?

Now I don't remember, but what was the problem with calling them
metaclasses?

metaclass already is used in other contexts in other languages, where it
stands for the (redefineable) class of a class. In ruby we usually just
override #new, in other languages they define their own class hierarchy,
so this has the same problem that virtual.
 
R

Robert Klemme

Mauricio Fernández said:
no...)

There's at least one case where you can know if the singleton class has
been created or not (singletons of singletons).

How come? What's special about singletons here?
And you can always know
if you're using evil.rb, of course :)

How exactly would you want to do it? I don't see how eval helps here.

The only way I can imagine is indirect: via instance_methods. But that
test can only assure, that the singleton class is created, you can't be
sure as long as the difference is empty:
s="" => ""
class << s ; def length() 1 end; end => nil
s.methods - s.class.instance_methods => []
class << s ; def foo;"foo"; end; end => nil
s.methods - s.class.instance_methods
=> ["foo"]

Regards

robert
 
D

David A. Black

Hi --

[I wrote:]

I think we're looking at this backwards in this discussion. We're
looking at it as: Objects have this weird class-like thing, so what
is it? I think it's better to look at it from the other end, like
this: Objects in Ruby can have methods added to them on a per-object
basis. That's a fundamental principle of Ruby (whether it is true of
other OO languages or not). The way Matz has chosen to implement this
is by associating a second, dedicated class with each object. That's
what this class actually *is* -- it's the fulfillment of that design,
not something growing off the design that has to be explained
separately.

While that's certainly true, we're (I am) here trying to grasp the nature
of these things to come up with a more appropriate name. At least that's
my understanding of the thread.

I agree, but I think the nature of singleton (or whatever) classes is
that they serve to manifest an important design feature of Ruby.
That being their nature, questions like whether they are identical to
other classes, etc., are secondary, not primary.
.... apart from the instance creation.

But that's the point: "being a class" in Ruby does not actually always
mean being instantiable. We know this, because there are classes that
aren't. To argue it the other way would be like saying: there are
variables that begin with "@", so variables in Ruby begin with "@";
therefore, "var" can't be a variable. (Don't worry -- I'm completely
aware of what can be said both for and against this analogy :) But
I still think it's good to let the language talk to us, rather than
the other way around.)
How about "instance_class"?

Interesting... though kind of weird that an object would be an
instance of something other than its instance_class :)


David
 
D

David A. Black

Hi --

There's at least one case where you can know if the singleton class has
been created or not (singletons of singletons).

Can you elaborate and/or give an example of what you mean?
And you can always know if you're using evil.rb, of course :)

Still holding out for a name change :)


David
 
M

Mauricio Fernández

How come? What's special about singletons here?
NameError: undefined local variable or method `foo' for #<Class:#<Class:#<Object:0x401fdd20>>>
from (irb):5

How exactly would you want to do it? I don't see how eval helps here.

eval is evil, but I really meant evil.rb :)
=> #<Class:#<Object:0x4032e35c>>

hence
=> true
 
M

Mauricio Fernández

Hi --



Can you elaborate and/or give an example of what you mean?

See my other response to Robert's post.
The reason is in rb_make_metaclass:

if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
RBASIC(klass)->klass = klass;
RCLASS(klass)->super = RBASIC(rb_class_real(RCLASS(obj)->super))->klass;
}
 
R

Robert Klemme

Mauricio Fernández said:
NameError: undefined local variable or method `foo' for
# said:
from (irb):5

Hm, but what about:
eval is evil, but I really meant evil.rb :)

Oops. I wasn't aware of evil.rb and assumed an evil pun. :) Shame on
me...
ObjectSpace._id2ref(o.internal.klass.to_i/2).instance_methods.include?
"foo"
=> true
=> #<Class:#<Object:0x4032e35c>>

hence
end
=> nil
=> true

Hm, well ok. But is there an equivalent without evil.rb, i.e. with
"normal" Ruby code? I know that you can access all kinds of internals if
you write an extension, but AFAIK you can't know whether there is a
singleton class or not. Please correct me if I'm wrong here...

Kind regards

robert
 

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

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top