Object_* and instance_* methods

David A. Black wrote:

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.

I'm starting to see your point. If we follow to its extreme the logic of having a consistent prefix for all metaprogramming methods, we wind up with a huge number of methods that can be considered to be metaprogramming. Taking Object.instance_methods and removing aliases and methods meant to be overridden, I get:

class
extend
freeze
frozen?
instance_eval
instance_of?
instance_variable_get
instance_variable_set
instance_variables
is_a?
method
methods
object_id
private_methods
protected_methods
public_methods
respond_to?
send
singleton_methods
taint
tainted?
untaint

Forcing all those methods to have an object_ or instance_ prefix is self-evidently nonsense. Therefore being a metaprogramming method *cannot* be the basis of using those prefixes.

But while I don't like the sound of "object_is_a?", I still like the sound of "object_class" and "object_method". And I am starting to realized that the reason is those methods represent /attributes/ of the object while "is_a?" or "taint" are /actions/. In the case of attributes, "object_" is not merely a prefix but an adjective to the ambiguous noun "id". Same for "class" of "method". It makes the methods sound natural, unlike slapping a prefix in front of an action verb. If I follow that line of reasoning, object_send and instance_send may be bad ideas. Unless we accept that some exceptions are inevitable, like instance_variable_[gs]et.

Don't we just love semantics? :wink:

Daniel

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 Mar 7, 6:00 am, Brian Candler <B.Cand...@pobox.com> wrote:

On Wed, Mar 07, 2007 at 07:46:56PM +0900, Brian Candler 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:

This suggestion has been around a long time, Ara reintroduced it
recentaly as "Pervasives". And yes, it is the easiest to implement and
doesn't require any change to Ruby's core. However it suffers from a
few issues.

1) In very rare cases you might actually have a good reason to "trick"
a caller. So still being able to override, say #object_class for
instance, while very dangerous, may nonetheless be desirable --and it
may be as simple as an AOP-like monitor which would have no real
effect on functionality.

2) Having two ways to get the same information isn't as helpful.
People will still use the old way b/c it's easier and they know it.
You still won't be able to use common terms like #class or #send in
your modules. (Of course we could get rid of the old methods
altogether, but I got a feeling that won't go over well).

3) Using external functions has a very detering inertia of being long
winded. Metaprogramming tends to use a lot of these calls in tight
loc. If one has to type Meta.send(obj, meth) intsead of obj.send(meth)
more than a few times, the code qucikly starts to become much less
readable. That may seem silly, but in the end people just won't use it
b/c of this (assuming they still have the other option).

4) It's a lot slower. It would need implementation in Ruby core anyway
to fix this issue.

T.

···

On Mar 7, 5:56 am, Pit Capitain <p...@capitain.de> wrote:

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 examplehttp://bracha.org/mirrors.pdffor a discussion. I
like this approach.

Correction...

    namespace :meta do

      def send(obj, meth, *args)

should be def send(meth, *args)

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

      def class(obj)

should be def class

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

But anyway, you get the idea.

T.

How is is_a? an action? To me it looks like a predicate which is a
truth-valued function.

To me an action is something which, at least, potentially effects a
state change.

Not that you're wrong from your point of view, it's just evidence of
how tricky and personal such categorizations really are.

···

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

But while I don't like the sound of "object_is_a?", I still like the
sound of "object_class" and "object_method". And I am starting to
realized that the reason is those methods represent /attributes/ of the
object while "is_a?" or "taint" are /actions/.

--
Rick DeNatale

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

David A. Black wrote:
> 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.

I'm starting to see your point. If we follow to its extreme the logic of
having a consistent prefix for all metaprogramming methods, we wind up
with a huge number of methods that can be considered to be
metaprogramming. Taking Object.instance_methods and removing aliases and
methods meant to be overridden, I get:

class
extend
freeze
frozen?
instance_eval
instance_of?
instance_variable_get
instance_variable_set
instance_variables
is_a?
method
methods
object_id
private_methods
protected_methods
public_methods
respond_to?
send
singleton_methods
taint
tainted?
untaint

Lets back up a second, these are "meta" because they are considered
"critical", right? The foremost reason for adding a prefix is simply
to make their name more uniq, so as be unlikely to clash with user-
defined method names. Most of these already fit that criteria. Any
that start with instance_ or object_ is uniq enough. And I would think
any of these having a punctuation mark is uniq enough as well. That
leaves:

class
extend
freeze
method
methods
private_methods
protected_methods
public_methods
send
singleton_methods
taint
untaint

Now I've always felt the methods, public_methods, private_methods and
protected_methods and singleton_methods were quite wasteful. One
method would suffice for all five, this has been discussed before. And
if we went ahead and did that and called that method #object_methods
and along with it had #object_method. Then all those are good to go
too. Leaving:

class
extend
freeze
send
taint
untaint

Now we all seem to agree that it at least makes sense to say
object_class to go along with object_id. And while I know there's
resistance to object_send (and instance_send) it makes a heck of a lot
of sense mnemonically. So if we could just go with that then there are
only four methods left:

extend
freeze
taint
untaint

I now sure about extend, but as for the last three. if these are
really critical then I'd take Daniel's idea about "action" to heart
and add a ! to them. They pretty much embody the idea of "danger"
methods.

  freeze!
  taint!
  untaint!

There may be few methods forgotten here, and they can be considered,
but we're not after perfection --for that these methods would probably
have to be moved out of Object. But we at least gain a system much
improved.

T.

···

On Mar 7, 9:47 am, Daniel DeLorme <dan...@dan42.com> wrote:

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 09:09:59PM +0900, Trans wrote:

On Mar 7, 6:00 am, Brian Candler <B.Cand...@pobox.com> wrote:
> On Wed, Mar 07, 2007 at 07:46:56PM +0900, Brian Candler 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.

Hi --

Now we all seem to agree that it at least makes sense to say
object_class to go along with object_id. And while I know there's
resistance to object_send (and instance_send) it makes a heck of a lot
of sense mnemonically. So if we could just go with that then there are
only four methods left:

extend
freeze
taint
untaint

This reminds me of the routine where George Carlin reduces the ten
commandments to one :slight_smile:

I now sure about extend, but as for the last three. if these are
really critical then I'd take Daniel's idea about "action" to heart
and add a ! to them. They pretty much embody the idea of "danger"
methods.

freeze!
taint!
untaint!

Action != danger :slight_smile: Also, ! methods always come in pairs. That's
not enforced by the language, of course, but it's the convention: the
! indicates the dangerous version of a pair of methods where there's
also a non-dangerous version. Those three methods state clearly what
they do in their names, and they don't occur in pairs, so it's not a !
situation.

David

···

On Thu, 8 Mar 2007, Trans 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)

Rick DeNatale wrote:

But while I don't like the sound of "object_is_a?", I still like the
sound of "object_class" and "object_method". And I am starting to
realized that the reason is those methods represent /attributes/ of the
object while "is_a?" or "taint" are /actions/.

How is is_a? an action? To me it looks like a predicate which is a
truth-valued function.

You are entirely right of course. I was thinking of "verb", really, and incorrectly converted that to "action" when in fact not all verbs are actions.

foo.method == foo's method (noun). what kind of method?
   -> foo.object_method
   -> foo.instance_method
   -> foo.birth_control_method
foo.send(message) == foo sends (verb) a message. what kind of message?
   -> foo.send_object(message)
   -> foo.send_instance(message)
   -> foo.send_email(message)

But even Matz chose instance_variable_get over get_instance_variable...

Daniel

Trans wrote:

Now I've always felt the methods, public_methods, private_methods and
protected_methods and singleton_methods were quite wasteful. One
method would suffice for all five, this has been discussed before. And
if we went ahead and did that and called that method #object_methods

I kinda like that a little bit. We could have
   foo.object_methods.all/to_a
   foo.object_methods.private
   foo.object_methods.protected
   foo.object_methods.public
   foo.object_methods.singleton

But I'm not too concerned with "clutter". A basic Object could have a bazillion methods as far as I care, as long as they don't conflict with methods names that people can reasonably/possibly create on their own. "private_methods" already has the adjective "private" to qualify the ambiguous noun "methods", so changing that adjective to "object" is not much of an improvement. Adding an adjective to "methods" would be good but that is already done; methods is just an alias of public_methods.

Daniel

Hi --

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

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:

But we don't. The method names in Ruby are hand-crafted with great
care, and they show it. Also, when there are soup-like tendencies,
Matz is eager and happy to discuss them.

(I see the smiley but I'm concerned that the drift of this thread
could be seen as: Matz botched the method-naming thing, so we have to
intervene and figure out how to fix it.)

David

···

On 3/7/07, Brian Candler <B.Candler@pobox.com> wrote:

On Wed, Mar 07, 2007 at 09:09:59PM +0900, Trans wrote:
> On Mar 7, 6:00 am, Brian Candler <B.Cand...@pobox.com> wrote:
> > On Wed, Mar 07, 2007 at 07:46:56PM +0900, Brian Candler 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)

Hi --

> Now we all seem to agree that it at least makes sense to say
> object_class to go along with object_id. And while I know there's
> resistance to object_send (and instance_send) it makes a heck of a lot
> of sense mnemonically. So if we could just go with that then there are
> only four methods left:

>> extend
>> freeze
>> taint
>> untaint

This reminds me of the routine where George Carlin reduces the ten
commandments to one :slight_smile:

Lol! :slight_smile:

> I now sure about extend, but as for the last three. if these are
> really critical then I'd take Daniel's idea about "action" to heart
> and add a ! to them. They pretty much embody the idea of "danger"
> methods.

> freeze!
> taint!
> untaint!

Action != danger :slight_smile:

But what danger doesn't invlove action?

Also, ! methods always come in pairs. That's
not enforced by the language, of course, but it's the convention: the
! indicates the dangerous version of a pair of methods where there's
also a non-dangerous version. Those three methods state clearly what
they do in their names, and they don't occur in pairs, so it's not a !
situation.

I think that's just a general occurance. Not a rule. In anycase
there's a good reason for a different type of "danger" --don't
override me!

T.

···

On Mar 7, 4:44 pm, dbl...@wobblini.net wrote:

On Thu, 8 Mar 2007, Trans wrote:

No, that wasn't intended at all.

I'm not arguing that the methods are badly named, although I sympathise with
the argument that #class awkwardly clashes with the 'class' keyword.

By "soup" I mean that even an empty object has a zillion methods inherited
from Object and Kernel. I don't dispute there are good reasons for each one;
e.g. if you had to write "$stdout.puts" instead of "puts", or
"Kernel.require 'foo'", those would be off-putting. All I'm saying is that
objects will always have these zillion methods, unless Matz decides to
modularise it, so adding a few more (like extra reflection methods under
your own naming scheme) wouldn't make any difference.

Matz *could* separate this all out:

  class Object < BasicObject
    include Kernel
    include Reflection
    ... etc
  end

But then, you still wouldn't get any benefit unless you explicitly created
your new objects under BasicObject rather than Object, so there's not much
practical benefit.

Regards,

Brian.

···

On Wed, Mar 07, 2007 at 10:07:01PM +0900, David A. Black wrote:

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

But we don't. The method names in Ruby are hand-crafted with great
care, and they show it. Also, when there are soup-like tendencies,
Matz is eager and happy to discuss them.

(I see the smiley but I'm concerned that the drift of this thread
could be seen as: Matz botched the method-naming thing, so we have to
intervene and figure out how to fix it.)

Hi --

···

On Thu, 8 Mar 2007, Trans wrote:

Also, ! methods always come in pairs. That's
not enforced by the language, of course, but it's the convention: the
! indicates the dangerous version of a pair of methods where there's
also a non-dangerous version. Those three methods state clearly what
they do in their names, and they don't occur in pairs, so it's not a !
situation.

I think that's just a general occurance. Not a rule. In anycase
there's a good reason for a different type of "danger" --don't
override me!

Well... we'd have an awful lot of !'s if it started meaning that :slight_smile:
I've never heard Matz discuss the ! in a way that made it sound like
he would use it outside of method pairs, and I'm still not sure what
the purpose would be. It's not a language-level rule, but I think
it's the intent behind the !.

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)

Maybe all danger involves action, but not all action involves danger.

···

On Thu, Mar 08, 2007 at 07:17:48AM +0900, Trans wrote:

> > freeze!
> > taint!
> > untaint!
>
> Action != danger :slight_smile:

But what danger doesn't invlove action?

Hi --

I didn't write what follows so I guess the quoting got hosed :slight_smile:

> >> 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.
> >
> >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:
>
> But we don't. The method names in Ruby are hand-crafted with great
> care, and they show it. Also, when there are soup-like tendencies,
> Matz is eager and happy to discuss them.
>
> (I see the smiley but I'm concerned that the drift of this thread
> could be seen as: Matz botched the method-naming thing, so we have to
> intervene and figure out how to fix it.)

No, that wasn't intended at all.

I know; I was just concerned that, with the references to soup and
things being half-implemented and so on, people could get the
impression that this was all being ascribed to some failing on the
part of Matz. If so, that would be a meta-impression; I definitely
know that you're not saying that :slight_smile:

I'm not arguing that the methods are badly named, although I sympathise with
the argument that #class awkwardly clashes with the 'class' keyword.

So do I. self.class is definitely not a high point. And the biggest
problem is probably that it brought about the creation of the #type
method, which to this day, I believe, makes it harder than it should
be for people to get the type != class thing.

By "soup" I mean that even an empty object has a zillion methods inherited
from Object and Kernel. I don't dispute there are good reasons for each one;
e.g. if you had to write "$stdout.puts" instead of "puts", or
"Kernel.require 'foo'", those would be off-putting. All I'm saying is that
objects will always have these zillion methods, unless Matz decides to
modularise it, so adding a few more (like extra reflection methods under
your own naming scheme) wouldn't make any difference.

Matz *could* separate this all out:

  class Object < BasicObject
    include Kernel
    include Reflection
    ... etc
  end

But then, you still wouldn't get any benefit unless you explicitly created
your new objects under BasicObject rather than Object, so there's not much
practical benefit.

There must be a way (though I'm multitasking too much right now to
figure it out) to do something like create your own modules that
consist of methods that already exist in other modules. Or something.
That would be kind of interesting.

David

···

On 3/7/07, Brian Candler <B.Candler@pobox.com> wrote:

On Wed, Mar 07, 2007 at 10:07:01PM +0900, David A. Black 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)

Hmm. Clearly this sort of stuff could go into a module; then anything which
is interested in reflections could do, say,

    def process(a)
      a.extend Reflection
      a.instance_methods.each { ... }
      ...
    end

Unfortunately, this causes a permanent change in the object being reflected
upon - an unintended Heisenberg-like side-effect.

However, suppose you could temporarily add a module:

    def process(a)
      b = a.insert Reflection
      b.instance_methods.each { ... }
      ...
    end

That would give an easy API, less cumbersome than Meta.instance_methods(a),
but not pollute the general method namespace of the object. Even better,
because the Reflection module was just inserted, when there is a name clash
then the method in Reflection will take precedence (e.g. b.class where a
already had overridden 'class')

I think this could be implemented using a proxy object / delegator.

But actually, there's no need to pass any method calls through. You could
just have a Reflector object:

    def process(a)
      b = Reflector.new(a)
      b.instance_methods.each { ... }
      ...
    end

B.

···

On Wed, Mar 07, 2007 at 10:36:31PM +0900, David A. Black wrote:

>Matz *could* separate this all out:
>
> class Object < BasicObject
> include Kernel
> include Reflection
> ... etc
> end
>
>But then, you still wouldn't get any benefit unless you explicitly created
>your new objects under BasicObject rather than Object, so there's not much
>practical benefit.

There must be a way (though I'm multitasking too much right now to
figure it out) to do something like create your own modules that
consist of methods that already exist in other modules. Or something.
That would be kind of interesting.

I think that could be a damn good idea!

Is there room for two exceptions?

  class Object
    def object
      @_object_reflector ||= Reflector.new(self)
    end
    def instance
      @_instance_reflector ||= InstanceReflector.new(self)
    end
  end

  foo.object.id
  foo.instance.send(:P)

(*ducks*)
T.

···

On Mar 7, 9:02 am, Brian Candler <B.Cand...@pobox.com> wrote:

I think this could be implemented using a proxy object / delegator.

But actually, there's no need to pass any method calls through. You could
just have a Reflector object:

    def process(a)
      b = Reflector.new(a)
      b.instance_methods.each { ... }
      ...
    end