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?
cheers.
-a
···
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi
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).
"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
While experimenting with this, I discovered something interesting: it
is possible to instantiate a metaclass. By duping a metaclass, you
regain the ability to instantiate it, apparently without losing any
functionality.
name = "Jack Smith"
def name.reverse
split.reverse.join ", "
end
name.reverse #==> "Smith, Jack"
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
···
On 4/28/05, Assaph Mehr <assaph@gmail.com> wrote:
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).
["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?
(?)
hmm. that will probably work. what i want is something for my attributes
module that does
class C
attribute 'foobar' #=> defines instance method
class_attribute 'foobar' #=> defines class instance method
class << self
attribute 'foobar' #=> defines class instance method
end
end
eg. i want the metacode generater 'attribute' to be context sensitive as in
def attribute name
if inside_metaclass? and self.is_a? Class
class_attribute name
else
...
end
end
the above should work but may give unforseen problems... any spring to mind?
cheers.
-a
···
On Fri, 28 Apr 2005, Assaph Mehr wrote:
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).
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi
hmm. i like this more than the pure matching version - which seemed a bit
fragile.
seems like i could do
harp:~ > cat a.rb
class Object
def inside_metaclass?
begin
allocate()
false
rescue NoMethodError
false
rescue TypeError => e
%r/virtual class/i =~ e.to_s and true
end
end
end
obj = Object::new
klass = Class::new
p inside_metaclass? #=> false
class << obj
p inside_metaclass? #=> true
end
class << klass
p inside_metaclass? #=> true
end
class << self
p inside_metaclass? #=> true
end
harp:~ > ruby a.rb
false
true
too.
now - any opinions on whether this violates POLS or not:
···
On Fri, 29 Apr 2005, Robert Klemme wrote:
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
#
# my attributes module - hoping to become a collection of better 'attr' like
# metamethods...
#
require 'attributes'
class C
#
# define a class attr => used like C::foo
#
class_attribute 'foo'
class << self
#
# define a class attr => used like C::foobar
#
# note that this would be the SAME as using class_attribute 'foobar'
# outside of metaclass
#
attribute 'foobar'
end
end
so, you see, Object::attribute would be context sensitive to being inside a
metaclass or not - if inside a Class.metaclass it's defining a class
attribute, else an instance attribute.
thoughts?
-a
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi
While experimenting with this, I discovered something interesting: it
is possible to instantiate a metaclass. By duping a metaclass, you
regain the ability to instantiate it, apparently without losing any
functionality.
name = "Jack Smith"
def name.reverse
split.reverse.join ", "
end
name.reverse #==> "Smith, Jack"
Any thoughts? Am I strange for finding this a bit surprising?
Well, duping a metaclass doesn't really return a metaclass. That is,
it is no longer a thing tied to one object; it's just a free-roaming
class like any other. (I won't comment on whether or not that's
"surprising" -- *wanting* to #dup a singleton class is surprising
enough for me.
What you may have noticed is that #dup-ing a class doesn't copy it's
singleton-class-ness, but #clone-ing does. Replace your `dup' with
`clone', and you'll get an error, since you can't instantiate the
clone:
irb(main):001:0> s = ''
=> ""
irb(main):002:0> (class << s; self; end).clone.new
TypeError: can't create instance of singleton class
from (irb):2:in `new'
from (irb):2
The weirdness here is that the clone is a singleton class (as implied
by the error message), but can have no instance!
On 4/28/05, Ara.T.Howard <Ara.T.Howard@noaa.gov> wrote:
i like a method like this
def inside_metaclass?
# to be implemented
end
While experimenting with this, I discovered something interesting: it
is possible to instantiate a metaclass. By duping a metaclass, you
regain the ability to instantiate it, apparently without losing any
functionality.
name = "Jack Smith"
def name.reverse
split.reverse.join ", "
end
name.reverse #==> "Smith, Jack"
Any thoughts? Am I strange for finding this a bit surprising?
--
email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi
While experimenting with this, I discovered something interesting: it
is possible to instantiate a metaclass. By duping a metaclass, you
regain the ability to instantiate it, apparently without losing any
functionality.
name = "Jack Smith"
def name.reverse
split.reverse.join ", "
end
name.reverse #==> "Smith, Jack"
Any thoughts? Am I strange for finding this a bit surprising?
I find it pretty startling. I've often wondered whether there was a
way to do essentially this. I'd concluded there wasn't. Maybe, at
the time, there wasn't....
I subjected it to one further test, to make sure that the
name2.reverse is actually a different method (since if two objects
were sharing a singleton method, that would have to be considered a
bug):
class << name
def reverse
"hi"
end
end
name.reverse # hi
name2.reverse # Doe, John
"hello".reverse # olleh <= just to be totally sure
Hmmmm, it's still daytime in Paris, so we may yet learn of some
limitation or reason to avoid it...
* Mark Hubbart <discordantus@gmail.com> [2005-04-30 16:35:16 +0900]:
While experimenting with this, I discovered something interesting: it
is possible to instantiate a metaclass. By duping a metaclass, you
regain the ability to instantiate it, apparently without losing any
functionality.
As is said later, duping the object 'erases' the singleton methods
while 'cloning' carries them over.
I've always considered duping as a nice way of erasing the 'specialness'
of an object while returning it to its natural state.
o = Object.new
def o.inspect; `clear`; end
p o # clears the screen
o = o.dup
p o # #<Object:0x3e3d4>
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.
Lionel: If 'class << ' itself seems a little odd to you, read on...
The class << obj notation can be used in ways that you might not
expect. Since ruby syntax is not as ridged as some other languages,
any expression can take the place of 'obj' in that notation. For
example, if you want to create a temporary/mock object of some sort:
def clear
class << (a = Object.new)
def inspect() `clear` end
end
end
(this example was pulled right out of my irbrc)
As you can see, 'a' was assigned to, and then the resulting object was
opened for modification. So this code:
class <<
# do stuff
end
... just creates an anonymous array and opens it's metaclass (or
idioclass or singleton class or virtual class, whatever). However, the
array is never assigned to a variable, so it will probably be garbage
collected pretty soon. You will probably never see this exact thing in
someone's code, but it is possible.
cheers,
Mark
···
On 4/29/05, Florian Groß <florgro@gmail.com> wrote:
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.
now - any opinions on whether this violates POLS or not:
#
# my attributes module - hoping to become a collection of better 'attr'
like
# metamethods...
#
require 'attributes'
class C
# define a class attr => used like C::foo
class_attribute 'foo'
# define an instance attr => C::new.bar
attribute 'bar'
class << self
# define a class attr => used like C::foobar
attribute 'foobar'
end
end
The way it works is analogous to "def attribute_name", which is
unsurprising. I like it.
I also like the setter capability of the getter methods (setting attributes
in a block passed to the constructor looks very clean), and I'm sure I'll be
using your module a in future.