[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

determining when inside 'class << self'

Ara.T.Howard

4/29/2005 3:43:00 AM

25 Answers

Assaph Mehr

4/29/2005 6:24:00 AM

0


Ara.T.Howard wrote:
> i like a method like this
>
> def inside_metaclass?
> # to be implemented
> end
>
> class C
> class << self
> p inside_metaclass? #=> true
> end
>
> p inside_metaclass? #=> false
> end
>
> p inside_metaclass? #=> false
>
> class << []
> p inside_metaclass? #=> true
> end
>
> can this be done?


Would you settle for testing if you're inside an anonymous class?
Anonymous classes have names that look like:
#<Class:...>

So you can define your method as:

def inside_metaclass?
Integer === (self.to_s =~ /^#<Class:/)
end

Which will evaluate to true for anonymous classes. Since (I believe)
all meta-classes are anonymous that can give you a pretty good guess
(or at least has the same result as your sample).

Out of curiosity I've run:
ObjectSpace.each_object { |o| p [o, o.class] if o.to_s =~ /^#<Class:/ }

Which returned ~30 such objects (anonymous classes, unless I'm
mistaken). So unless you're opening an anonymous class, you should be
OK (and I'm not even sure you can reopen an anonymous class).


HTH,
Assaph

Mark Hubbart

4/29/2005 6:46:00 AM

0

On 4/28/05, Assaph Mehr <assaph@gmail.com> wrote:
>
> Ara.T.Howard wrote:
> > i like a method like this
> >
> > def inside_metaclass?
> > # to be implemented
> > end
> >
> > class C
> > class << self
> > p inside_metaclass? #=> true
> > end
> >
> > p inside_metaclass? #=> false
> > end
> >
> > p inside_metaclass? #=> false
> >
> > class << []
> > p inside_metaclass? #=> true
> > end
> >
> > can this be done?
>
> Would you settle for testing if you're inside an anonymous class?
> Anonymous classes have names that look like:
> #<Class:...>
>
> So you can define your method as:
>
> def inside_metaclass?
> Integer === (self.to_s =~ /^#<Class:/)
> end
>
> Which will evaluate to true for anonymous classes. Since (I believe)
> all meta-classes are anonymous that can give you a pretty good guess
> (or at least has the same result as your sample).

To expand on that... metaclasses have a peculiar inspect value. This
code is breakable, but probably only if you try to:

class Class
def metaclass?
id = inspect[/\A\#<Class:\#<.+?\:0x(.+?)>>\Z/, 1]
ObjectSpace._id2ref(id.to_i(16)/2) if id
end
end

The metaclass? method will return nil if the receiver is not a
metaclass, or it's instance if it *is* a metaclass. Use it like this:

class << (a="test")
p self.metaclass? #==> prints "test"
end

class Foo
p self.metaclass? #==> prints nil
end

There's probably a safer way to do this using ruby/dl, or evil.rb. I
don't know, though.

cheers,
Mark

> Out of curiosity I've run:
> ObjectSpace.each_object { |o| p [o, o.class] if o.to_s =~ /^#<Class:/ }
>
> Which returned ~30 such objects (anonymous classes, unless I'm
> mistaken). So unless you're opening an anonymous class, you should be
> OK (and I'm not even sure you can reopen an anonymous class).
>
> HTH,
> Assaph
>
>



Carlos

4/29/2005 10:33:00 AM

0

["Ara.T.Howard" <Ara.T.Howard@noaa.gov>, 2005-04-29 06.04 CEST]
> i like a method like this
>
> def inside_metaclass?
> # to be implemented
self.is_a?(Class) && self.name.empty?
(?)
> end


Carlos

4/29/2005 10:41:00 AM

0

[Carlos <angus@quovadis.com.ar>, 2005-04-29 12.33 CEST]
> ["Ara.T.Howard" <Ara.T.Howard@noaa.gov>, 2005-04-29 06.04 CEST]
> > i like a method like this
> >
> > def inside_metaclass?
> > # to be implemented
> self.is_a?(Class) && self.name.empty?
> (?)
self.is_a?(Class) && !self.ancestors.include?(self)
(!)
> > end


George Ogata

4/29/2005 12:12:00 PM

0

"Ara.T.Howard" <Ara.T.Howard@noaa.gov> writes:

> i like a method like this
>
> def inside_metaclass?
> # to be implemented
> end
>
> class C
> class << self
> p inside_metaclass? #=> true
> end
>
> p inside_metaclass? #=> false
> end
>
> p inside_metaclass? #=> false
>
> class << []
> p inside_metaclass? #=> true
> end
>
> can this be done?

Is this cheating?:

#include "ruby.h"

VALUE metaclass_p(VALUE self) {
if (FL_TEST(self, FL_SINGLETON))
return Qtrue;
else
return Qfalse;
}

void Init_test(void) {
rb_define_method(rb_cClass, "metaclass?", metaclass_p, 0);
}



Florian Groß

4/29/2005 12:31:00 PM

0

Mark Hubbart wrote:

> To expand on that... metaclasses have a peculiar inspect value. This
> code is breakable, but probably only if you try to:
>
> [...]
>
> There's probably a safer way to do this using ruby/dl, or evil.rb. I
> don't know, though.

I'm not sure if you consider this safer, but while you can subclass
anonymous and normal classes you can not do so for idioclasses so this
ought to work:

class Class
def idioclass?()
Class.new(self)
return true
rescue TypeError
return false
end
end

Of course somebody /could/ raise a TypeError in the inherited hook, but
that is quite unlikely to happen.

evil-ruby can of course check the actual RTYPE of the class which is
unbreakable, but that is a dependency you might not want to have.



Ara.T.Howard

4/29/2005 2:09:00 PM

0

Lionel Thiry

4/29/2005 2:37:00 PM

0

Ara.T.Howard a écrit :
> class << []
> p inside_metaclass? #=> true
> end
>

Sorry for the newbie question, but what does this mean?

--
Lionel Thiry

Personal website: http://users.skynet....

Robert Klemme

4/29/2005 2:57:00 PM

0


"Ara.T.Howard" <Ara.T.Howard@noaa.gov> schrieb im Newsbeitrag
news:Pine.LNX.4.62.0504282141220.19121@harp.ngdc.noaa.gov...
>
> i like a method like this
>
> def inside_metaclass?
> # to be implemented
> end
>
> class C
> class << self
> p inside_metaclass? #=> true
> end
>
> p inside_metaclass? #=> false
> end
>
> p inside_metaclass? #=> false
>
> class << []
> p inside_metaclass? #=> true
> end
>
> can this be done?

Yes, like this:

class Object
def inside_metaclass?() false end
end

class Class
def inside_metaclass?
begin
self.allocate
false
rescue TypeError => e
/virtual class/i =~ e.to_s and true
end
end
end

irb(main):058:0> class <<Object.new; p inside_metaclass? end
true
=> nil
irb(main):059:0> p inside_metaclass?
false
=> nil
irb(main):060:0> class String; p inside_metaclass? end
false
=> nil

Cheers

robert

Florian Groß

4/29/2005 5:46:00 PM

0

Lionel Thiry wrote:

>> class << []
>> p inside_metaclass? #=> true
>> end
>
> Sorry for the newbie question, but what does this mean?

class << obj enters the idioclass of an object which is a class that
contains method that will only be defined for that particular object.

When

obj = "Pacman -> (<"

then

class << obj
def reverse() ">) <- Pacman" end
end

is the same as

def obj.reverse() ">) <- Pacman" end

So we provide a custom implementation of reverse() for a single method
only -- you can also use this for adding completely new functionality.

So why is the class << obj syntax necessary at all?

To apply other class abilities to a single object. You might want to
create an accessor for only one single object:

obj = Array.new
class << obj
attr_accessor :creator
end

obj.creator # => nil
obj.creator = ENV["username"]
obj.creator # => "flgr" (your result may vary ;))
obj << "foo"
obj << "bar"
obj # => ["foo", "bar"]

But even after that code:

ary = Array.new
ary.creator # raises NoMethodError

Oh, and p obj just outputs an object's state for debugging. (It is the
same as doing puts obj.inspect)