determining when inside 'class << self'

A

Ara.T.Howard

Hmmmm, it's still daytime in Paris, so we may yet learn of some limitation
or reason to avoid it... :)

he __is__ amazing isn't he!

-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
===============================================================================
 
J

Jim Freeze

* Mark Hubbart said:
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>

Try this in irb (but you don't need the 'p's)
 
M

Mark Hubbart

Hi --



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....

Sure enough, this doesn't work in 1.6.8. Also, the singleton class
inspects as "String" in 1.6.8, which I find interesting.
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... :)

indeed :)

cheers,
Mark
 
C

Christoph

Jim said:
* Mark Hubbart <[email protected]> [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.
It's true that duping erases class method for general
objects - it's FALSE for Module objects!

---
module A
def self.bla
puts "bla"
end
end

A.dup.bla # bla


Foo = class << 1.0; def self.bar; puts "bar" end; self end.dup

class Bar < Foo
puts ancestors.join(" < ")
# Bar < Foo < Float < Precision < Numeric < Comparable < Object <
Kernel
end

Bar.bar # bar
---

I am not sure if I would read to much into this behavior.
Here is another curiosity. If you clone a singleton you end up
with a "virtual class" which is not the virtual class of any living
Object. I guess the only usefully thing you can do with this class
is duping it:)

---
Once = class << one = []; self end
Twice = Once.clone

begin
Class.new(Twice)
rescue TypeError=> mes
puts mes # can't make subclass of virtual class
end

class Once
def okay
end
end

class Twice
def fails
end
end

one.okay

begin
one.fails
rescue NoMethodError=> mes
puts mes # undefined method `fails' for []:Array
end

found = nil
ObjectSpace.each_object do |o|
found = o if Twice == class << o; self end
end

p found # nil

class Third < Twice.dup
end

p Third.new(1){3} # [3]
 
J

Jim Freeze

* Christoph said:
It's true that duping erases class method for general
objects - it's FALSE for Module objects!

---
module A
def self.bla
puts "bla"
end
end

A.dup.bla # bla

I'm not sure I understand your point here.
A typical use is below:

irb(main):001:0> module M
irb(main):002:1> def fred; "fred"; end
irb(main):003:1> end
=> nil
irb(main):004:0> class C; end
=> nil
irb(main):005:0> c = C.new
=> #<C:0x46b10>
irb(main):006:0> c.extend M
=> #<C:0x46b10>
irb(main):007:0> c.fred
=> "fred"
irb(main):008:0> c = c.dup
=> #<C:0x871d8>
irb(main):009:0> c.fred
NoMethodError: undefined method `fred' for #<C:0x871d8>
from (irb):9
from :0

But, if you have module methods and extended an object,
what would be the point? How do module methods show up
in extended objects? I thought they didn't.
 
C

Christoph

Jim said:
I'm not sure I understand your point here.

A typical use is below:

irb(main):001:0> module M
irb(main):002:1> def fred; "fred"; end
irb(main):003:1> end
=> nil
irb(main):004:0> class C; end
=> nil
irb(main):005:0> c = C.new
=> #<C:0x46b10>
irb(main):006:0> c.extend M
=> #<C:0x46b10>
irb(main):007:0> c.fred
=> "fred"
irb(main):008:0> c = c.dup
=> #<C:0x871d8>
irb(main):009:0> c.fred
NoMethodError: undefined method `fred' for #<C:0x871d8>
from (irb):9
from :0

But, if you have module methods and extended an object,
what would be the point? How do module methods show up
in extended objects? I thought they didn't.
Cloning a Module object and cloning an object that
was extend by Module is very different and cloning
a Class object is jet another subject - speaking of which

The following abuse creates an unprintable Class object


---
class O
end

P = class << O; self end.dup

class << P
p superclass
rescue SystemStackError => mes
puts mes # stack level too deep
end
 

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

Similar Threads


Members online

Forum statistics

Threads
473,796
Messages
2,569,645
Members
45,364
Latest member
CrypttoTaxSofttware

Latest Threads

Top