Mark Hubbart <discordantus / gmail.com> writes:

> 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"
>   
>   # dup name's metaclass
>   nameclass = class << name; self; end.dup
>   
>   name2 = nameclass.new  "John Doe"
>   name2.reverse  #==> "Doe, John"
>
> 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!