#meta

I’ve come across a number of occasions where methods like
#class_attr_accessor, or #module_alias_method are defined. It’s nice
to have those, but it seems to me this isn’t very DRY since the
methods for these things already exist in the class domain (ie.
singleton class). So what do others think of this instead:

module Kernel

# Provides access to an object's metaclass (singleton class)
# by-passing access provisions. So for example:
#
#   class X
#     meta.attr_accesser :a
#   end
#
#   X.a = 1
#   X.a #=> 1

def meta
  @_meta_functor ||= Functor.new do |op,*args|
    (class << self; self; end).__send__(op,*args)
  end
end

end

Personally, I’ve wished I could name the method #class and/or #module,
but obviously that’s not doable. In any case, do you think this is a
better approach? Are there any serious disadvantages to it? Or do you
prefer a myriad of special class level methods? If so why?

If you are not familiar with Facets Functor, it’s your basic higher
order message:

class Functor

# Privatize all methods except vital methods and #binding.
private(*instance_methods.select { |m| m !~ /(^__|^binding$)/ })

def initialize(&function)
  @function = function
end

def to_proc
  @function
end

# Any action against the functor is processesd by the function.
def method_missing(op, *args, &blk)
  @function.call(op, *args, &blk)
end

end

Thanks,
T.

On 22.03.2008 14:15, Trans wrote:

#
  end

order message:
def to_proc
Thanks,
T.

I am feeling stupid because I seem to overlook something: what is the
advantage of your approach vs.

class Object
def meta
class<<self;self;end
end
end

? As far as I can see your functor in this case simply delegates all
method invocations to the singleton class. Why not directly use /
return it?

While I think about it you could even do:

class Object
def meta(&b)
cl = class<<self;self;end
cl.class_eval(&b) if b
cl
end
end

class Some
meta do
attr_accessor :foo

 def incr
   self.foo += 1
 end

end
end

Kind regards

robert

On Mar 22, 2008, at 06:39 , Robert K. wrote:

I am feeling stupid because I seem to overlook something: what is
the advantage of your approach vs.

class Object
def meta
class<<self;self;end
end
end

Your approach mentarbates less, so trans doesn’t like it as much.

Hi Robert,

On Mar 22, 9:39 am, Robert K. [email protected] wrote:

method invocations to the singleton class. Why not directly use /
return it?

Try it:

class X
meta.attr_accessor
end
NoMethodError: private method `attr_accessor’ called for #Class:X
from (irb):7

class Some
meta do
attr_accessor :foo

 def incr
   self.foo += 1
 end

end
end

There’s no need for meta at all, you could just use “class << self”
directly,

class Some
class << self
attr_accessor :foo

  def incr
    self.foo += 1
  end
end

end

But just as some people prefer to use “def self.foo”, it’s nice to use
module level methods like #class_attr_accessor. That’s were #meta
comes in as generalized form rather than defining class level
equivalents for all possible methods.

T.

On 3/22/08, Ryan D. [email protected] wrote:

Your approach mentarbates less, so trans doesn’t like it as much.

Along these lines, note Stu Halloway’s blog post about the definition
of Object#metaclass in facets vs. other places and the ensuing
commentary:

I’d seen lots of examples of metaclass being defined the same way as
Robert’s proposed meta method above, and had never seen the more
complex implementation in facets until Stu bumped into problems
because use was using facets ‘feature’ of taking a block.

I totally agree with the consensus in the comments that the simpler
definition is better. I also side with Jim W. about the
distinction between metaclass and singleton class or eigenclass or
whatever you want to call them.

Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Mar 22, 2:39 pm, “Rick DeNatale” [email protected] wrote:

class<<self;self;end

I’d seen lots of examples of metaclass being defined the same way as
Robert’s proposed meta method above, and had never seen the more
complex implementation in facets until Stu bumped into problems
because use was using facets ‘feature’ of taking a block.

I totally agree with the consensus in the comments that the simpler
definition is better.

Actually in Facets, #singelton_class is defined witht the simpler
definition. #meta_class is not. However, I don’t agree that the
simplier case is somehow better. The issue is that Ruby will no-op a
block regardless. For example:

def x; “1”; end
x{“whatever”} #=> 1

So it has nothing per se to do with the definition of #meta_class.
It’s an aspect of Ruby, and the fact that there are two definitions of
this floating around out there. So between the two, I tend toward not
wasting name space. If supporting the block takes nothing away from
the regular usage, and it reads better, then whats the issue exactly?

I also side with Jim W. about the
distinction between metaclass and singleton class or eigenclass or
whatever you want to call them.

That’s Smalltalk not Ruby. I understand the distinction people want to
draw, but in Ruby they are the same construct.

T.

On Mar 22, 3:53 pm, “Robert D.” [email protected] wrote:

That’s Smalltalk not Ruby. I understand the distinction people want to
draw, but in Ruby they are the same construct.

Thats why I think that overloading the expression “singleton class” is
somehow confusing.
Just my 2cents.
R.

I agree with that. But nothing else seems to stick. Even today I
thought of “domain class”, but I’m not sure that has all the right
connotations either.

T.

On 3/22/08, Trans [email protected] wrote:

I also side with Jim W. about the
distinction between metaclass and singleton class or eigenclass or
whatever you want to call them.

That’s Smalltalk not Ruby. I understand the distinction people want to
draw, but in Ruby they are the same construct.

I respectfully disgree.

Singleton classes in Ruby are an implementation construct which is
used for two distinct purposes:

  1. To provide a place to put instance behavior. For example

    a = “abc”
    def a.foo
    :foo
    end

  2. To provide a class for a class, i.e. a metaclass.

One difference is that the first can’t have subclasses, while
singleton classes used as metaclasses can and must since the
inheritance chain of metaclasses parallels the inheritance chain of
their instances. The otehr is that metaclasses is the class of a
class, not an arbitrary object. For all practical purposes, the second
kind acts exactly as metaclasses do in Smalltalk, and Matz was quoted
as such in the 2nd ed of the Pickaxe. Unfortunately many in the Ruby
community misunderstood that page as equating metaclass with singleton
class rather than seeing that although singleton classes are used to
implement metaclasses in Ruby, all singleton classes are NOT
metaclasses, a term which has a meaning even beyond Smalltalk of being
the class of a class.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Sat, Mar 22, 2008 at 1:39 PM, Robert K.
[email protected] wrote:

class Some

    robert

Indeed - I’m using almost identical code in doodle[1] but using the
name #singleton_class instead of #meta :slight_smile:

def singleton_class(&block)
  sc = (class << self; self; end)
  sc.module_eval(&block) if block_given?
  sc
end

@Trans - doesn’t #meta clash with an openuri attribute? I’ve just
removed it as an alias to #singleton_class in doodle for that reason.
FWIW, I’m considering renaming #singleton_class to avoid clashing with
someone else’s definition. Perhaps, something like
#the_method_formerly_and_variously_known_as_singleton_eigen_or_meta_class
:wink:

Regards,
Sean

[1] http://doodle.rubyforge.org

On 22.03.2008 20:21, Trans wrote:

? As far as I can see your functor in this case simply delegates all
method invocations to the singleton class. Why not directly use /
return it?

Try it:

class X
meta.attr_accessor
end
NoMethodError: private method `attr_accessor’ called for #Class:X
from (irb):7

So then the only (?) advantage of your proposal is that you can use
private methods like ordinary methods.

There’s no need for meta at all, you could just use “class << self”
directly,

True enough. And “class << self … end” is not as ugly as “class
<<self;self;end” for getting at the instance itself.

But just as some people prefer to use “def self.foo”, it’s nice to use
module level methods like #class_attr_accessor. That’s were #meta
comes in as generalized form rather than defining class level
equivalents for all possible methods.

I see. Thanks for the enlightenment.

Kind regards

robert

On Mar 22, 7:13 pm, “Sean O’Halpin” [email protected] wrote:

@Trans - doesn’t #meta clash with an openuri attribute? I’ve just
removed it as an alias to #singleton_class in doodle for that reason.

Yes, at the moment. But I recently checked the latest version of
openuri, and it no longer conflicts.

FWIW, I’m considering renaming #singleton_class to avoid clashing with
someone else’s definition. Perhaps, something like
#the_method_formerly_and_variously_known_as_singleton_eigen_or_meta_class
:wink:

Sorry, I think that’s been used before :wink:

T.

That’s Smalltalk not Ruby. I understand the distinction people want to
draw, but in Ruby they are the same construct.
Thats why I think that overloading the expression “singleton class” is
somehow confusing.
Just my 2cents.
R.

T.


http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

On Sat, Mar 22, 2008 at 11:28 PM, Rick DeNatale
[email protected] wrote:

I respectfully disgree.

  1. To provide a class for a class, i.e. a metaclass.

One difference is that the first can’t have subclasses, while
singleton classes used as metaclasses can and must since the
inheritance chain of metaclasses parallels the inheritance chain of
their instances.
Hmm, this indeed would make me think about the possibility to use
metaclass as a special case of a singleton class of a
module.

(1) class << Object.new; self end is a singleton class but not a
metaclass
(2) class << Module::new; self end is a metaclass and a singleton class
by (1)

I never really noticed if this is used consistently as such, my bad
AAMOF.

Cheers
Robert


http://ruby-smalltalk.blogspot.com/


Whereof one cannot speak, thereof one must be silent.
Ludwig Wittgenstein

On Mar 23, 7:19 am, Robert K. [email protected] wrote:

But just as some people prefer to use “def self.foo”, it’s nice to use
module level methods like #class_attr_accessor. That’s were #meta
comes in as generalized form rather than defining class level
equivalents for all possible methods.

I see. Thanks for the enlightenment.

Honestly, I’m not all that keen about the method. I’m not sure what it
is about it that bothers me --I can’t quite put my finger on it. Which
is why I’ve brought this topic up. But then I consider the
alternative, defining a set of convenience methods:

class_attr
class_attr_reader
class_attr_writer
class_attr_accessor
class_alias_method
class_remove_method
class_undef_method

And as much as any one of those suits me just fine, it seems very
wasteful to define so many when one method does the job.

T.

On 23.03.2008 13:05, Trans wrote:

Wait a minute… could we set the methods we’re interested in here to
=> Module
Looks good!!! Not sure why this never occurred to me before. See
anything wrong with this approach?

At the moment the only thing that bothers me is to change the visibility
of some methods of the core lib. I mean, they must be restricted for a
reason…

Kind regards

robert

On Mar 23, 7:19 am, Robert K. [email protected] wrote:

So then the only (?) advantage of your proposal is that you can use
private methods like ordinary methods.

There’s no need for meta at all, you could just use “class << self”
directly,

Well, yea.

Wait a minute… could we set the methods we’re interested in here to
protected instead of private? And, as you suggest, just use the
singleton class?

def singleton
class<<self;self;end
end
=> nil
class Module
protected :attr_accessor
end
=> Module
class X
singleton.attr_accessor :x
end
=> nil
X.x
=> nil
X.attr_accessor :y
NoMethodError: protected method `attr_accessor’ called for X:Class
from (irb):11

Looks good!!! Not sure why this never occurred to me before. See
anything wrong with this approach?

T.