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 –

On Thu, 1 Mar 2007, Daniel DeLorme wrote:

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

[email protected] 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 –

On Thu, 1 Mar 2007, Daniel DeLorme wrote:

[email protected] 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.

  1. 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 Mar 1, 6:53 am, [email protected] wrote:

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.

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 5, 1:19 pm, [email protected] 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.

T.

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

On 3/5/07, Trans [email protected] wrote:

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.

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 Mar 5, 3:17 pm, “David A. Black” [email protected] wrote:

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 3/6/07, Daniel DeLorme [email protected] wrote:

taken together I think they have weight. When one solution solves 5-6
problems, that’s the smell of good design to me.

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.


Rick DeNatale

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

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

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

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

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]

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

  2. (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”)

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

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

Brian C. schrieb:

----- 8< -------------------------------------------------------
end
f = Foo.new
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

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

# 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:

Regards,

Brian.

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.

On Mar 7, 6:00 am, Brian C. [email protected] wrote:

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

And this is straightforward to implement:

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

Woh! Now you’re undermining the very reasons for doing this. If we all
go willy nilly naming these things whatever we want we’ll be in a
worse can of soup thatn we were to begin with.

T.

On Wed, Mar 07, 2007 at 09:09:59PM +0900, Trans wrote:

worse can of soup thatn we were to begin with.
I was just trying to make something which might be more palatable to the
OP.

If I understand rightly, he would rather use foo#object_class,
foo#object_send, foo#object_method etc. as a way of lexically
identifying
these methods as “meta programming methods”. I showed how he could
implement
exactly what he asks for, where he wants it, without demanding changes
to
the core Ruby language.

However I agree with you - explicit reflections (which take an object as
an
argument, rather than being methods on all objects) are probably a
better
idea, to avoid the clutter.

I think the argument is moot unless Matz decides to go this way in a
later
version of Ruby; otherwise we’ll still have method soup anyway :slight_smile:

However I understand that Ruby 2.x is going to have a BasicObject /
BlankSlate though - in which case, maybe the reflections could all be
put in
a module.

Regards,

Brian.

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

And this is straightforward to implement:

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

another issue:

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