#meta

T

Trans

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

Robert Klemme

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.

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
 
R

Ryan Davis

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

Rick DeNatale

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:

http://blog.thinkrelevance.com/2008/2/12/how-should-metaclass-work

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 Weirich about the
distinction between metaclass and singleton class or eigenclass or
whatever you want to call them.
 
T

Trans

Hi Robert,

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?

Try 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

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

Trans

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

http://blog.thinkrelevance.com/2008/2/12/how-should-metaclass-work

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

Robert Dober

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

Trans

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

Rick DeNatale

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

Sean O'Halpin

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

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

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
;)

Regards,
Sean

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

Robert Klemme

Try it:

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
 
T

Trans

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

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.

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
;)

Sorry, I think that's been used before ;)

T.
 
R

Robert Dober

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

Trans

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

Trans

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

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

Robert Klemme

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?

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?

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
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top