Object_* and instance_* methods

A while back there was a proposal to use a standard naming scheme for meta-programming methods. It went like this:

   object_id
   object_class (instead of class)
   object_send (instead of send)
   object_method (instead of method)

Then for all the methods that bypass access restrictions:

   instance_send (instead of funcall)
   instance_eval
   instance_exec
   instance_variable_get
   instance_variable_set
   instance_variables

The discussion didn't go much farther then but I'd like to reignite the bikeshed. Personally I think it's a brilliant idea; sure the method names are longer but that seems perfectly acceptable to me since meta-programming should not be used that often. The naming is consistent and obvious, it avoids ugliness like __send__, it reduces chances of naming conflict (CgiRequest#method, Email#send), it allows a simple pattern match to recognize any meta-programming methods, and it's already half implemented. Are there any other people who support this idea?

Daniel

Hi --

A while back there was a proposal to use a standard naming scheme for meta-programming methods. It went like this:

object_id
object_class (instead of class)
object_send (instead of send)
object_method (instead of method)

Why object_method?

Then for all the methods that bypass access restrictions:

instance_send (instead of funcall)
instance_eval
instance_exec

I wish there were a way to name these without components to the name
that you have to "just know". I actually don't know the difference
between instance_eval and instance_exec, and I suspect I will be
looking it up frequently in the future :slight_smile:

I'm certainly in favor of not having funcall, for reasons enumerated
at length in earlier threads (q.v. if you have some spare time...).
I've lost track a bit of where that stands.

instance_variable_get
instance_variable_set
instance_variables

The discussion didn't go much farther then but I'd like to reignite the bikeshed. Personally I think it's a brilliant idea; sure the method names are longer but that seems perfectly acceptable to me since meta-programming should not be used that often.

I'd say it's more that they should be reasonably conspicuous.

The naming is consistent and obvious, it avoids ugliness like __send__, it reduces chances of naming conflict (CgiRequest#method, Email#send), it allows a simple pattern match to recognize any meta-programming methods, and it's already half implemented. Are there any other people who support this idea?

I'm more interested in the individual decisions -- like avoiding
__send__ by having some relatively non-vulnerable alternative. I'm
not big on grouping "metaprogramming" methods together, and I wouldn't
want to see decisions made collectively for them. I think a lot of
what's great about Ruby is how hand-crafted it is, so to speak. But I think most of the names you've suggested sound good. I'm not
sure about object_method, though.

David

···

On Thu, 1 Mar 2007, Daniel DeLorme wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

dblack@wobblini.net wrote:

Why object_method?

1. consistence: it's a meta-programming method
2. avoid collisions: e.g. ActionController::CgiRequest#method

You could even restrict object_method to public methods and use
instance_method to bypass access restrictions. It sounds like a proliferation of methods but if they are properly isolated under
a namespace, does it really matter how many methods there are?

I wish there were a way to name these without components to the name
that you have to "just know". I actually don't know the difference
between instance_eval and instance_exec, and I suspect I will be
looking it up frequently in the future :slight_smile:

Hey! Same for me! :smiley:

Daniel

Hi --

Why object_method?

1. consistence: it's a meta-programming method

They're all just methods, though. I'm uneasy with assigning clusters
of methods to super-categories. I think the results are better in the
end if choices are made at a more granular level: find the best name
for exactly what a given method is purporting to do. Clustering is
itself a "meta"-thing.

2. avoid collisions: e.g. ActionController::CgiRequest#method

I was thinking that collisions were less likely with #method, but I
guess they're still fairly likely.

David

···

On Thu, 1 Mar 2007, Daniel DeLorme wrote:

dblack@wobblini.net wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Yet the methods we're talking about in particular are rather "meta"-
things.

Naming convention are very powerful b/c they ease the burden on the
human mind , simplifying complexities, thus easing learning and
allowing for higher abstraction. Case in point I was recently asked to
add Module#instance_method? to Facets. My immediately thought was,
"great idea", since I instantly knew what was being asked by the name
of it. Only thing is, when I went to implement it, I realized we
already had it --it would just be an alias for #method_defined?.
method_defined? is an okay name for this functionality, but
instance_method? is better because it conforms to a recognizable
pattern along with #instance_method and #instance_methods. This may
not seem like much, but many small things can quickly add up.

I think Richard Feynman said it best, "never underestimate the power
of notation", or something like that.

T.

···

On Mar 1, 6:53 am, dbl...@wobblini.net wrote:

Hi --

On Thu, 1 Mar 2007, Daniel DeLorme wrote:
> dbl...@wobblini.net wrote:
>> Why object_method?

> 1. consistence: it's a meta-programming method

They're all just methods, though. I'm uneasy with assigning clusters
of methods to super-categories. I think the results are better in the
end if choices are made at a more granular level: find the best name
for exactly what a given method is purporting to do. Clustering is
itself a "meta"-thing.

Hi --

···

On Tue, 6 Mar 2007, Trans wrote:

I think Richard Feynman said it best, "never underestimate the power
of notation", or something like that.

I don't underestimate it -- I just don't like the idea of decisions
being made about naming on the basis of membership in a category like
"metaprogramming".

David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

I think you are though, becuase beloging to this category isn't the
basis. That just happens to be the case. The basis is the beneficial
effect that the naming would have on coding, in particular the effect
on method_missing and privatizing or removing all methods that don't
start with instance_ and object_, as well as the effect it would have
on one's ability to more easily learn and use Ruby.

T.

···

On Mar 5, 1:19 pm, dbl...@wobblini.net wrote:

Hi --

On Tue, 6 Mar 2007, Trans wrote:
> I think Richard Feynman said it best, "never underestimate the power
> of notation", or something like that.

I don't underestimate it -- I just don't like the idea of decisions
being made about naming on the basis of membership in a category like
"metaprogramming".

Have another look at the thread. Daniel was adducing
metaprogramming-ness as a reason for naming methods a certain way, not
something that happens to be the case. I was discussing this and
expressing misgivings about that approach.

In any case, you're talking about metaprogramming operations *on*
method names (removing them, using method_missing), which is different
from the matter of naming methods because what those methods do is
metaprogramming. I think that, too, is a tricky road to travel. I'd
rather see each method have the best possible name, since it's going
to be used more as a method than as a string to be matched for method
removal purposes and so forth. Moreover, it's very hard to predict
exactly which batch of methods someone is going to want to remove;
they may or may not all fall into a secondary category like
metaprogramming.

David

···

On 3/5/07, Trans <transfire@gmail.com> wrote:

On Mar 5, 1:19 pm, dbl...@wobblini.net wrote:
> Hi --
>
> On Tue, 6 Mar 2007, Trans wrote:
> > I think Richard Feynman said it best, "never underestimate the power
> > of notation", or something like that.
>
> I don't underestimate it -- I just don't like the idea of decisions
> being made about naming on the basis of membership in a category like
> "metaprogramming".

I think you are though, becuase beloging to this category isn't the
basis. That just happens to be the case. The basis is the beneficial
effect that the naming would have on coding, in particular the effect
on method_missing and privatizing or removing all methods that don't
start with instance_ and object_, as well as the effect it would have
on one's ability to more easily learn and use Ruby.

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
   (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Have another look at the thread. Daniel was adducing
metaprogramming-ness as a reason for naming methods a certain way, not
something that happens to be the case. I was discussing this and
expressing misgivings about that approach.

Yes he was, but as a consequence of other needs, not just because
there is such a category. So that my point: any argument against doing
this based on the fact that it's a catagorization, I feel is missing
the point. No other cataegories are being considered. It's not about a
general pattern of naming methods according to categories. Rather it's
one paticular set of methods that have some special needs/uses that
would be better served by a consistant naming pattern.

In any case, you're talking about metaprogramming operations *on*
method names (removing them, using method_missing), which is different
from the matter of naming methods because what those methods do is
metaprogramming.

Yes, exactly. And I think this is what Daniel really meant too.

I think that, too, is a tricky road to travel. I'd
rather see each method have the best possible name, since it's going
to be used more as a method than as a string to be matched for method
removal purposes and so forth.

Well, what is best? That's the very question. Figuring out what is
best means taking into account all the uses. Yes, plain usage is
important, so we don't really want methods that are too long or
esoteric. Is that the criteria you are using? Yet there are other
important considerations. An important one being that "meta" methods
be easily discernable so they can be readuly worked around in
delegators --and delegators are very common in OOP. To me it's just a
big bonus that this works out to a pattern that is already largely
(subconsciously?) followed in Ruby, namely using the prefixes object_
and instance_, and consequently brings all the benefits of quick
recognition and eased learning. So again, what is best?

Moreover, it's very hard to predict
exactly which batch of methods someone is going to want to remove;
they may or may not all fall into a secondary category like
metaprogramming.

It's quite easy really. Most of the time it's the same ones' b/c most
of the time is for delegation. And in a case of numerous exeptions,
we'd be no worse off then we were before anyway. Surely you must see
that?

T.

···

On Mar 5, 3:17 pm, "David A. Black" <dbl...@wobblini.net> wrote:

Trans wrote:

In any case, you're talking about metaprogramming operations *on*
method names (removing them, using method_missing), which is different
from the matter of naming methods because what those methods do is
metaprogramming.

Yes, exactly. And I think this is what Daniel really meant too.

I meant both, really. I named about 5-6 "problems" that each benefited from this naming scheme. Even though each of them was pretty small, taken together I think they have weight. When one solution solves 5-6 problems, that's the smell of good design to me.

Daniel

I don't have a dog in this fight, but I'm interested since it seems to
touch on naming and categorization.

I must have missed that list of 5-6 problems, a quick re-read of the
thread doesn't provide an obvious list, but maybe I'm just not reading
it right.

But I have to observe, that the problem with categories is that they
often appear to be universal, but actually turn out to be personal
and/or cultural.
There's an interesting cognitive linguistics book called "Women, Fire,
and Dangerous Things." by George Lakoff with all kinds of evidence of
this.

Maybe it's not a direct analogy to this thread, but the problem gets
more serious when you try to build hierarchical categories. Lakoff
points out that most languages and culture agree about the most basic
categories, rocks are rocks, trees are trees, and birds are birds. But
when those categories get sorted into hierarchies differences emerge.
My interest in this first arose when thinking about the limitations of
statically typed class/type hierarchies which force types into a
particular factoring.

I guess I'm wandering off the topic of this thread, but my reaction to
"When one solution solves 5-6 problems, that's the smell of good
design to me." is maybe, if those are MY 5-6 problems, and it doesn't
interfere with my solving other, possibly more important problems.

I'm not sure that this "Swiss army knife" approach to design is an
unalloyed good.

···

On 3/6/07, Daniel DeLorme <dan-ml@dan42.com> wrote:

Trans wrote:
>> In any case, you're talking about metaprogramming operations *on*
>> method names (removing them, using method_missing), which is different
>> from the matter of naming methods because what those methods do is
>> metaprogramming.
>
> Yes, exactly. And I think this is what Daniel really meant too.

I meant both, really. I named about 5-6 "problems" that each benefited
from this naming scheme. Even though each of them was pretty small,
taken together I think they have weight. When one solution solves 5-6
problems, that's the smell of good design to me.

--
Rick DeNatale

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

Rick DeNatale wrote:

I must have missed that list of 5-6 problems, a quick re-read of the
thread doesn't provide an obvious list, but maybe I'm just not reading
it right.

- avoids ugliness like __send__
- reduces chances of naming conflict (CgiRequest#method, Email#send)
- allows simple pattern match to recognize present and future meta-programming methods (used for forwarding of non-meta methods)
- already half implemented.

ok, so that was 4, and not even all of them were problems. let's add:

- consistent naming makes methods easier to remember
- mnemonic for public vs. private interface
- avoid special keyword "class" which forces to use self.class

As Trans said, membership in a category like "metaprogramming" is not the basis. The basis is in the 7 points above.

Maybe it's not a direct analogy to this thread, but the problem gets
more serious when you try to build hierarchical categories. Lakoff
points out that most languages and culture agree about the most basic
categories, rocks are rocks, trees are trees, and birds are birds. But
when those categories get sorted into hierarchies differences emerge.

I agree that different hierarchies are possible but that doesn't mean we should avoid any hierarchy. Some organization is better than no organization. In the proposed case, metaprogramming methods are divided into 2 sub-hierarchies (object_* and instance_*). Might there be a different, orthogonal hierarchy? Yes. But that doesn't negate the usefulness of this one.

I'm not sure that this "Swiss army knife" approach to design is an
unalloyed good.

Oh, certainly not unalloyed; it's just my personal experience that when you have a solution for one problem (public send vs. private send) and then you find it happens to solve another problem (method forwarding), it's a good solution. And the fact that it's already half implemented means the pattern was already present but perhaps not conciously realized. Plus, it makes me feel warm and fuzzy inside :slight_smile:

Daniel

Rick DeNatale wrote:
>I must have missed that list of 5-6 problems, a quick re-read of the
>thread doesn't provide an obvious list, but maybe I'm just not reading
>it right.

- avoids ugliness like __send__
- reduces chances of naming conflict (CgiRequest#method, Email#send)
- allows simple pattern match to recognize present and future
meta-programming methods (used for forwarding of non-meta methods)
- already half implemented.

ok, so that was 4, and not even all of them were problems. let's add:

- consistent naming makes methods easier to remember
- mnemonic for public vs. private interface
- avoid special keyword "class" which forces to use self.class

I don't think any of those are actually stated as problems. I hope you don't
mind me putting words into your mouth if I restate them for you:

1. __send__ is ugly

2a.Sometimes reasonable user-chosen method names override meta-programming
   methods on Object like #method, #send and #class which other programs may
   reasonably expect to be present and functional in their normal way for
   all objects

   [Aside: this even happens for built-in classes, e.g. UDPSocket#send]

or (stronger):

2b.Sometimes reasonable user-chosen method names override methods on
   Object and Kernel (e.g. CgiRequest#method vs Object#method, Email#send vs
   Object#send, Semester#class vs Object#class, MyObject#test vs Kernel#test)
   thereby hiding those methods

   [Still also true for UDPSocket#send]

3. It is currently not possible to recognise all meta-programming methods
   via a simple pattern match on the method name

4. (Not sure how to recast this as a problem. Is this a subset of problem
   3? e.g. "it is possible to recognise *some* meta-programming methods via
   a simple pattern match on the method name, but not all")

5. Meta-programming method names in Ruby are inconsistent and hard to
   remember

6. Method names do not clearly distinguish between "private" and "public"
   interfaces

7a.method name #class conflicts with keyword 'class', forcing use of
   self.class to invoke the method

or (stronger):

7b.keyword 'class' conflicts with method name #class and local variables,
   forcing use of klass = Foo and self.class

Do you agree?

As Trans said, membership in a category like "metaprogramming" is not
the basis. The basis is in the 7 points above.

I disagree. Solutions to problems 2a, 3, 4, 5 hinge _crucially_ on an agreed
distinction between "normal" and "metaprogramming" methods. Problem 6 hinges
on an agreed distinction between "private and public interfaces"; perhaps
you mean the same thing here. (It's clearly not the same as Ruby's 'private'
and 'public' method modifiers)

Problems 1 and 2b are, IMO, ultimately a symptom of all method names on an
object falling into the same namespace. The only way consistent way to
separate them is by including a namespace as part of the method name. Using
the object's class name would be one solution:

   Object#object_class
   Object#object_send
   Object#object_private_methods
   Object#object_singleton_method_added
   ...

There is already a precedent here: Object#id was renamed to Object#object_id

However, a full solution to problem 2b would involve *all* methods on Object
being in a separate namespace. This quickly becomes stupid:

   Object#object_is_a?
   Object#object_nil?
   Object#object_eql?
   Object#object_to_s
   ...

Should it also apply to other built-in modules like Kernel (included in
every object) or Enumerable (included in many objects)?

   Kernel#kernel_puts
   Enumerable#enumerable_collect
   ... etc?

I think not. But if we choose some other basis for namespaces (e.g. "normal"
versus "metaprogramming") then again this crucially depends on recognising
which methods fall into which category, arguing this for each method.

Problem 7 is true of all keywords in the language, i.e. you can't have a
local variable or bare method name called 'if' or 'end'. It's a symptom of
keywords, local variables and receiverless method names falling into the
same namespace. I assume you don't want to tag these things Perl-style.

Since the set of reserved words in Ruby is very small, I don't think this is
a problem normally when choosing your own method names. But I agree that
it's unfortunate that Ruby has decided to use a name for a *built-in* method
which is also a reserved word.

From that point of view, I'd be happy to see #class changed to
#object_class, in the same way that #id was changed to #object_id

But what about send? It's already available in its own pseudo-namespace as
__send__. Should it instead be object_send? Perhaps. But whether the current
situation really constitutes "a problem" is a subjective matter, I feel.

Final point. If the requirement is that 'meta-programming' methods should be
available always on all objects, then I can offer a completely different
solution:

    # was: foo.class
    Object.class_of(foo)

    # was: foo.send(meth,*args)
    Object.send_to(foo, meth, *args)

    # was: foo.method(:bar)
    Object.method_of(foo, :bar)

That is, by making all these operations singleton methods of a module,
instead of (or as well as) instance methods which are present on all
objects, then there is never any chance of them being overriden by the
object itself. It's not very OO-like, but it *is* immune from this problem.

Making them module methods would also reduce the clutter in object instance
methods:

irb(main):001:0> class Foo; end; Foo.new.methods
=> ["dup", "hash", "private_methods", "extend", "nil?", "__send__",
"instance_eval", "tainted?", "class", "singleton_methods", "=~", "untaint",
"kind_of?", "object_id", "instance_variable_get", "respond_to?", "inspect",
"frozen?", "taint", "id", "public_methods", "equal?", "to_a", "method",
"clone", "protected_methods", "send", "freeze", "display",
"instance_variable_set", "type", "is_a?", "methods", "==", "instance_of?",
"===", "instance_variables", "__id__", "eql?", "to_s"]

(Incidentally, which of these are metaprogramming? What about "extend",
"taint", "freeze", "respond_to?")

Regards,

Brian.

···

On Wed, Mar 07, 2007 at 09:01:17AM +0900, Daniel DeLorme wrote:

Rick DeNatale wrote:
> I must have missed that list of 5-6 problems, a quick re-read of the
> thread doesn't provide an obvious list, but maybe I'm just not reading
> it right.
- avoids ugliness like __send__

__send__ was *supposed* to be ugly, because it's a signal that you're
doing something different.

- reduces chances of naming conflict (CgiRequest#method, Email#send)

Naming conflicts are okay, as long as there are non-conflicting names
(e.g., __send__ or whatever 1.9 is now calling it).

- allows simple pattern match to recognize present and future
meta-programming methods (used for forwarding of non-meta methods)

Erm. Pattern matching is somewhat useful, but I'm not sure that this
is something that would be automatic in any case.

-austin

···

On 3/6/07, Daniel DeLorme <dan-ml@dan42.com> wrote:
--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

And this is straightforward to implement:

----- 8< -------------------------------------------------------
module Meta
  def self.send(obj, meth, *args)
    Object.instance_method(:send).bind(obj).call(meth, *args)
  end

  def self.class(obj)
    Object.instance_method(:class).bind(obj).call
  end

  # etc
end

class Foo
  def send(*args)
    "whoo!"
  end
  def class
    "stupid!"
  end
end

f = Foo.new

puts f.class # stupid!
puts Meta.class(f).inspect # Foo

puts f.send(:object_id) # whoo!
puts Meta.send(f, :object_id) # -605608944
----- 8< -------------------------------------------------------

Implement all the methods you consider to be "metaprogramming" with whatever
names you think are appropriate. Stick it up as a module on rubyforge, in
case anyone comes across the same need as you. Job done, and no need to
change the core language :slight_smile:

Regards,

Brian.

···

On Wed, Mar 07, 2007 at 06:40:20PM +0900, Brian Candler wrote:

Final point. If the requirement is that 'meta-programming' methods should be
available always on all objects, then I can offer a completely different
solution:

    # was: foo.class
    Object.class_of(foo)

    # was: foo.send(meth,*args)
    Object.send_to(foo, meth, *args)

    # was: foo.method(:bar)
    Object.method_of(foo, :bar)

That is, by making all these operations singleton methods of a module,
instead of (or as well as) instance methods which are present on all
objects, then there is never any chance of them being overriden by the
object itself. It's not very OO-like, but it *is* immune from this problem.

Ah, that was a refreshing analysis. Thank's Brian!

I think you're spot on for the most part. Though I think you've
overdrawn the categorization a little. For instance these methods:

   Object#object_is_a?
   Object#object_nil?
   Object#object_eql?
   Object#object_to_s

are not needed since they are can be done in others way, eg. ===,
NilClass ===, etc. But you are absolutely right that this is not a
perfect solution. There was a really good conversation about this not
too long ago, and a couple of "perfect" solutions were put forth. See
the last half of the thread called "Little Things". Unfortunately Matz
doesn't seem inclined to take up any of these "tough" solutions. At
least he never chimes in when the conversation gets that far along. So
the solution of least resistance is to make some minor adjustments
where thie issue is most significant. Which means renaming a few of
the _most critical_ methods. Critical is a better categorzation than
Metaprogramming in this case.

But hey, I'm all for a perfect solution! And I thought the send
operator idea was a pretty damn good one.

T.

Hi --

Problems 1 and 2b are, IMO, ultimately a symptom of all method names on an
object falling into the same namespace. The only way consistent way to
separate them is by including a namespace as part of the method name. Using
the object's class name would be one solution:

   Object#object_class
   Object#object_send
   Object#object_private_methods
   Object#object_singleton_method_added
   ...

There is already a precedent here: Object#id was renamed to Object#object_id

The precedent thing is always tricky, though. One could also say:
this has already happened once, so we've filled the quota :slight_smile: Also, I
think #object_id was 100% about the difficulties with name conflicts,
which isn't an issue with #singleton_method_added.

However, a full solution to problem 2b would involve *all* methods on Object
being in a separate namespace. This quickly becomes stupid:

   Object#object_is_a?
   Object#object_nil?
   Object#object_eql?
   Object#object_to_s
   ...

Should it also apply to other built-in modules like Kernel (included in
every object) or Enumerable (included in many objects)?

   Kernel#kernel_puts
   Enumerable#enumerable_collect
   ... etc?

I think not. But if we choose some other basis for namespaces (e.g. "normal"
versus "metaprogramming") then again this crucially depends on recognising
which methods fall into which category, arguing this for each method.

And that's why I'd rather not get "meta" about it. It seems to me
that determining categorization for each method cannot be *better*
than determining what the method does and naming it based on that. In
particular, getting into an open-ended debate about what is and isn't
metaprogramming in Ruby is, I think, unpromising and wasteful.

Problem 7 is true of all keywords in the language, i.e. you can't have a
local variable or bare method name called 'if' or 'end'. It's a symptom of
keywords, local variables and receiverless method names falling into the
same namespace. I assume you don't want to tag these things Perl-style.

Since the set of reserved words in Ruby is very small, I don't think this is
a problem normally when choosing your own method names. But I agree that
it's unfortunate that Ruby has decided to use a name for a *built-in* method
which is also a reserved word.

From that point of view, I'd be happy to see #class changed to
#object_class, in the same way that #id was changed to #object_id

I'm personally in favor of #birth_class and #singleton_class, but I
don't think that has much traction.

(Incidentally, which of these are metaprogramming? What about "extend",
"taint", "freeze", "respond_to?")

Good question. My view is that it's all programming.[1] I think of the
term "metaprogramming", in connection with Ruby at least, as a
description of what the programming does, rather than what a given
method does.

David

[1] See, e.g., http://dablog.rubypal.com/2007/1/7/meta-shmeta-learning-ruby-horizontally

···

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
   (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

Brian Candler schrieb:

···

On Wed, Mar 07, 2007 at 06:40:20PM +0900, Brian Candler wrote:

Final point. If the requirement is that 'meta-programming' methods should be
available always on all objects, then I can offer a completely different
solution:

    # was: foo.class
    Object.class_of(foo)

    # was: foo.send(meth,*args)
    Object.send_to(foo, meth, *args)

    # was: foo.method(:bar)
    Object.method_of(foo, :bar)

That is, by making all these operations singleton methods of a module,
instead of (or as well as) instance methods which are present on all
objects, then there is never any chance of them being overriden by the
object itself. It's not very OO-like, but it *is* immune from this problem.

And this is straightforward to implement:

----- 8< -------------------------------------------------------
module Meta
  def self.send(obj, meth, *args)
    Object.instance_method(:send).bind(obj).call(meth, *args)
  end

  def self.class(obj)
    Object.instance_method(:class).bind(obj).call
  end

  # etc
end

class Foo
  def send(*args)
    "whoo!"
  end
  def class
    "stupid!"
  end
end

f = Foo.new

puts f.class # stupid!
puts Meta.class(f).inspect # Foo

puts f.send(:object_id) # whoo!
puts Meta.send(f, :object_id) # -605608944
----- 8< -------------------------------------------------------

Implement all the methods you consider to be "metaprogramming" with whatever
names you think are appropriate. Stick it up as a module on rubyforge, in
case anyone comes across the same need as you. Job done, and no need to
change the core language :slight_smile:

Brian, this looks a lot like the concept of "mirrors" in the language Self. See for example http://bracha.org/mirrors.pdf for a discussion. I like this approach.

Regards,
Pit

Alternatively, make your own methods on the objects themselves, giving them
whatever consistent naming scheme you feel like:

class Object
  def meta_class
    Object.instance_method(:class).bind(self).call
  end

  def meta_send(*args)
    Object.instance_method(:send).bind(self).call(*args)
  end

  #def method_missing(meth, *args)
  # return Object.instance_method($1).bind(self).call(*args) if
  # /^meta_(.*)$/ =~ meth.to_s
  # raise NoMethodError, "undefined method '#{meth}' for #{inspect}"
  #end
end

class Foo
  def send(*args)
    "whoo!"
  end
  def class
    "stupid!"
  end
end

f = Foo.new

puts f.class # stupid!
puts f.meta_class # Foo

puts f.send(:object_id) # whoo!
puts f.meta_send(:object_id) # -605608944

···

On Wed, Mar 07, 2007 at 07:46:56PM +0900, Brian Candler wrote:

And this is straightforward to implement:

another issue:

5) Doesn't encapsulate the original object.

I can offer a solution to that, though it still suffers some of the
other problems. I haven't tested this but it should work (and if not,
it can be fixed to do so):

  require 'facets/more/namespace'

  class Object

    namespace :meta do

      def send(obj, meth, *args)
        Object.instance_method(:send).bind(obj).call(meth, *args)
      end

      def class(obj)
        Object.instance_method(:class).bind(obj).call
      end

      # etc
    end

  end

  class Foo
    def send(*args)
      "whoo!"
    end
    def class
      "stupid!"
    end
  end

  f = Foo.new

  puts f.class # stupid!
  puts f.meta.class # Foo

  puts f.send(:object_id) # whoo!
  puts f.send(:meta).send(:object_id) # -605608944

T.