Minor Change Proposal for Classes 'Object' and 'Method'

On 1/23/07, [email protected] [email protected] wrote:

don’t think we’ll come to an agreement.
I completely agree, but I feel that the argument teaches me a lot.

end
Now we change the implementation of the method:

…we are still able to execute the old implementation. So, if I look at
this
example, I don’t think that

m.call

is really sending a message. It just executes the implementation it has
remembered in the context of the original object.

That is very interesting but funnily enough IMHO it makes it even more
counter-intuitive to call a m’s receiver.
As a matter of fact I know that I cannot go into the depth of the
implementation that is why I have asked the question:
“Do we agree that the only thing having a receiver is a message”
Obviously we do not.
But in that case, what can have a receiver? A method? A method-call? A
method object?

OMG we might end up in an endless loop.

…I would even say that the receiving part has occurred in step 1),
where
the object decides how it wants to react upon the message.

… by fixing the code, yep that is an excellent argument, but it is not
true in all cases

m= a.method(:x)
m.unbind
m.bind(a.class.new)

so at least the decision you were talking about was not final, the code
stays the same but the receiver changes.
I try hard to figure if one can argument as such in your setup, canyou?
or
are we still miles apart?

In step 2), the

object’s role is to execute a given piece of code in its context.

or the methods role to execute a given piece of code in a context in
which
the object it is bound to becomes the receiver.

Pit

Honestly Ara I am disappointed by the tone of your post, I do not
recognize
you, this is very subtle a discussion and the s***y word has just no
place
in it.
I would frankly ignore it by people I know less but…
Now if I overreact I apologize, I am not a native speaker.

very good points. frankly, i find the ‘potentiality’ arguments silly
since

 def m() furture_self end

end

but, of course, we don’t.

That is completely OT we were talking about Runtime “self” is perfectly
defined at execution of the method, while at point (x) receiver is not -
but
is in your setup I start to guess that now.
m = a.method(:x)
------(x)--------
a.call

you can put any code between the two lines as I have mentioned above.

the point is that, unless code executes as you write it, we are
always

deferring the framing context to the time of execution and chosing terms
that
make sense in that potential context. we use ‘server’ and ‘client’ even
if no
packets will be sent.

But given a server S and a client C, it would be incorrect to name S C’s
server before C has sent a packet to S. We are clearly talking runtime
and
not time of conception.

We are not saying that receiver is bad a name for an object. We think it
is
bad a name for a relationship between Method and the object it is bound
to
at a given state during runtime.
When the method is called the relationship between its bound object and
itself can be described as receiver before it is misleading.

‘producer’ and ‘consumer’ and meaningful event when no

events transpire. ‘source’ and ‘sink’ are perfect logical titles to relay
meaning as are ‘receiver’ and ‘message’. the eventuality or potentiality
have, imho, little to do with the use of these terms to define primary
relationships between objects.

regards.

-a


we can deny everything, except that we have the possibility of being
better.
simply reflect on that.

  • the dalai lama

Robert

Hi –

On Wed, 24 Jan 2007, Pit C. wrote:

hasn’t acted as a receiver yet. David et al. think this would be
def x
puts m.call # => x of #<C:0x2ae912c>
puts a.x # => new x of #<C:0x2ae912c>
puts m.call # => x of #<C:0x2ae912c>

object’s role is to execute a given piece of code in its context.

So, I would say that after

m = a.method(:x)

the object a has at least partly acted as a receiver.

David, could you live with that? :slight_smile:

If I can send people to you when they ask for an explanation of the
double meaning :slight_smile:

David

On Wed, 24 Jan 2007, Robert D. wrote:

Honestly Ara I am disappointed by the tone of your post, I do not recognize
you, this is very subtle a discussion and the s***y word has just no place
in it. I would frankly ignore it by people I know less but… Now if I
overreact I apologize, I am not a native speaker.

hi robert-

sorry to offend - i wasn’t even trying to stir the pot! i chose the ‘s’
word
precisely because the whole affair doesn’t seem worth having strong
feelings
on. i’ll bow out of the discussion then since my feelings on the topic
certainly aren’t strong - i just felt like people we’re splitting hairs
and
thought i’d point out other accepted terms where people could easily do
the
same, but don’t.

as always, i suppose it’s better to post working ruby code than rants in
english: they are more precise! :wink:

kind regards.

-a

On 1/23/07, [email protected] [email protected] wrote:

overreact I apologize, I am not a native speaker.
and
thought i’d point out other accepted terms where people could easily do
the
same, but don’t.

as always, i suppose it’s better to post working ruby code than rants in
english: they are more precise! :wink:

kind regards.

There are few people that could offend me, you can, you did not but I
found
it unpleasant to read no big deal, thx for the explanation.
Yes indeed that explains it, for me this argument is very important
but
that is also a good reason to bail out as taking things so much to heart
does not allow for a clear look.
Besides I have made my points, and there are more qualified people to
decide.

Would be interesting to get insulted in pure ruby code. :wink:
Cheers
Robert

-a

On Wed, 24 Jan 2007 02:10:08 +0900
“Phrogz” [email protected] wrote:

(right?).

To me (whom no one knows, or probably cares about), calling it target
would imply that it could be changed… calling it receiver correctly
implies the context of immutability.

[email protected] wrote:

On Wed, 24 Jan 2007, Pit C. wrote:
[snip]

So, I would say that after

m = a.method(:x)

the object a has at least partly acted as a receiver.

David, could you live with that? :slight_smile:

If I can send people to you when they ask for an explanation of the
double meaning :slight_smile:

FWIW, it totally makes sense to me for “m.receiver” to return the
object a in the above. Whether it’s a Method instance, or a MethodData
instance, we’re asking questions about the method itself…which
includes “what will happen when I call this method?”. Given that, and
given that I agree with Ara’s point about future references, I’m happy
to call the #probable_future_receiver just #receiver. It’s the only
receiver that the method knows about at the time of asking, anyhow
(right?).

Hi –

On Wed, 24 Jan 2007, [email protected] wrote:

class C
def m() furture_self end
end

but, of course, we don’t.

I’ve come to think that:

m = a.method(:x)
m.call

does not involve a receiving the message “x”, in any useful sense of
the term “receiving”. So I don’t think it’s just a matter of avoiding
“future” in a case where something will happen in the future; rather,
it’s a different scenario from a.x. It’s avoiding “receiver” in a
case where the object in question is not the receiver of the message
in question.

But I’m in a tiny minority on every phase and nuance of this, so
that’s probably that :slight_smile:

David

[email protected] wrote:

in question.
I love the direction and depth that this discussion has taken and
continues to take. Fascinating tying down of abstract concepts :slight_smile:

David, if you don’t think of it as “receiving” the message, what do you
think of it as doing instead?

In Pit’s 2 step (find method associated with a message, execute the
code for that method), the word ‘receive’ doesn’t exist, except for the
implicit “I handed you a message that you’re supposed to find the
method for.” So let’s look at “m.call”.

That’s invoking the method with the ‘self’ set to ‘a’, right? Is it the
“bound_object” for the method?

[email protected] wrote:

does not involve a receiving the message “x”, in any useful sense of
the term “receiving”. So I don’t think it’s just a matter of avoiding
“future” in a case where something will happen in the future; rather,
it’s a different scenario from a.x. It’s avoiding “receiver” in a
case where the object in question is not the receiver of the message
in question.

But I’m in a tiny minority on every phase and nuance of this, so
that’s probably that :slight_smile:

I would avoid using the term ‘reciever’ for wholly different reason –
it has a sense of direction. not a big deal, but directional words can
sometimes have unsuspected consequences in how statements read.

As an alternative I will suggest ‘subject’ --as in the subject of a
sentence or predicate.

T.

“Phrogz” [email protected] writes:

(I personally don’t have a use case, but its certainly possible in some
scenarios.)

Let me try to remember it… I actually grepped the logs:

Dec 08 14:14:05 i want to use ordinary ruby modules as a
mean to extend a lambda based object system

Anyway, the case was I had a callback that was a module method, and I
wanted an easy way to turn it into a proc.

irb(main):001:0> module M; def foo; “foo!”; end; end
=> nil
irb(main):002:0> M.instance_method(:foo)
=> #<UnboundMethod: M#foo>

I imagine this to be useful for building DSLs, bundling callbacks etc,
too? At least, allow binding unbound methods to nil without
raising… that would make the not-existing self explicit, too:

irb(main):004:0> M.instance_method(:foo).bind(nil)
TypeError: bind argument must be an instance of M

On 1/23/07, [email protected] [email protected] wrote:

def m() self end

I’ve come to think that:

m = a.method(:x)
m.call

does not involve a receiving the message “x”, in any useful sense of
the term “receiving”. So I don’t think it’s just a matter of avoiding
“future” in a case where something will happen in the future; rather,
it’s a different scenario from a.x.

Sorry Ara I promised to bail out but I am just asking a question, just
too
curious.

David I am losing you here, probably you just look further than me but
as
well on a conceptional view as on an implementation’s view (method_call
in
eval.c if I recall correctly) m.call just sends the message :x to the
object
it is bound to.
If you avoid that notion, what else could there be? Method invocation
without message passing would this have benefits on the conceptional
level?
Hmm yes indeed it might close the discussion about receiver but I feel
it
would open a difficulty in describing this kind of invocation. Maybe it
would be worth it.

Far above my horizon but eager to learn.

It’s avoiding “receiver” in a

case where the object in question is not the receiver of the message
in question.

But I’m in a tiny minority on every phase and nuance of this, so
that’s probably that :slight_smile:

Yes indeed if you prefer to answer offlist I would be very happy too.
OTOH
someone who has gone through the trouble and effort of going through a
paradigm change will always be a minority first, right (c.f. my
signature)

David


Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (Ruby for Rails)
(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)

Cheers
Robert

If you haven’t read the parent message to this, this won’t make any
sense…

When I first wrote out:

obj.x(1,2) # 1
obj.resolve_then_apply(:x, 1, 2) # 2
obj.resolve(:x).apply(1,2) # 3

I saw this interesting possibility:

obj.resolve(:x, 1).apply(2)

I don’t have a very strong functional programming knowledge but I
believe this is an example of currying. It suggests that Kernel#method
and Module#instance_method could be be extended to have this
functionality:

dfirst = Array.instance_method(:delete, 1)
a = [1,2]
dfirst.bind(a).call
a # [2]

It would be nice if you could stuff this curried method back into
the class under a new name. The problem is that you can’t pass an
UnboundMethod instance to Module#define_method. UnboundMethod#to_proc
doesn’t exist and even if it did, it would be a pretty strange
instance of Proc since it would not be callable. This concept was
also suggested by Christian N…

Maybe there is some room to play around with the semantics of
methods/blocks/procs?

Gary W.

Robert D. schrieb:

(… something like the following …)

ma = a.method(:x)
mb = ma.unbind.bind(b)

Robert, this is a nice counter example to what I’ve written. In this
case the object “b” surely hasn’t received anything. So I guess its role
is really only that of a #bound_object.

Regards,
Pit

Warning: The following is pretty long but it has an interesting
surprise ending. At least it surprised me and I even think David will
find it quite satisfying (and maybe even Matz).

On Jan 23, 2007, at 12:54 PM, [email protected] wrote:

in question.

But I’m in a tiny minority on every phase and nuance of this, so
that’s probably that :slight_smile:

I have no way of knowing who is in the minority on this issue but I
very much agree with Robert D.'s sentiments: “… I feel that
the argument teaches me a lot”.

The only reason that I keep tugging at this thread is that David
had thrown into doubt my assumption that every method in Ruby
executes within the context of a ‘receiving’ object which is
syntactically identified by ‘self’. I’ve generally found David’s
thinking on the more dusty corners of Ruby semantics to be very
illuminating so his suggestion that the concept of ‘receiver’ didn’t
apply with respect to instances of Method came out of left field for me.

I wonder if we can brake the logjam a bit by thinking about the
situation in a different way. Given:

class A
def x(b,c); self; end
end

obj = A.new

consider the following snippets of code:

obj.x(1,2) # 1
obj.foo_then_bar(:x, 1, 2) # 2
obj.foo(:x).bar(1,2) # 3

Case 1 is just the normal method invocation.

Case 2 is a way to name the method via an expression but is otherwise
the same as case 1. The name ‘foo_then_bar’ hints that this is a two
step process.

Case 3 explicitly breaks up case 2 into two distinct steps.

Lets look at the same code with some different terminology:

obj.x(1,2) # 1
obj.resolve_then_apply(:x, 1, 2) # 2
obj.resolve(:x).apply(1,2) # 3

I’ve tried to pick names that suggest appropriate semantics without
dragging in the controversial semantics we’ve been talking about.
This suggests that:

f = obj.resolve(:x)

must return an object that encapsulates a reference to obj and also
encapsulates a reference to the definition of A#x found by
‘resolving’ :x relative to obj. This object must also respond to
‘apply’ such that

f.apply(1,2)

causes A#x to be called with the arguments 1 and 2.

Of course I hope everyone who is still reading has figured out that
obj.resolve_then_apply(:x, 1, 2) is just our old friend ‘send’:

obj.send(:x, 1, 2)

And within this context we’ve been happily saying things like:

The message :x is sent to obj.

obj is the receiver of the message :x

When A#m executes, ‘self’ points to obj.

When A#m executes, obj is the implicit receiver.

obj receives message :x, searches for a matching method, and
then executes the method with arguments 1 and 2.

As long as ‘send’ is viewed on the outside as a complete process
the send/receive terminology works quite fine. But…

… if we think of the process not as ‘send’ but instead as
‘resolve_then_apply(:x, 1,2)’ or ‘resolve(:x).apply(1,2)’ then
the send/receive metaphor starts to fall apart.

It wasn’t until I finally wrote all this out that I really started
to understand what David was getting at. When I started writing
this post I didn’t expect to end up at this point.

I believe David has been suggesting all along that if we hit the
pause button just after the ‘resolution’ process has finished but
before the ‘apply’ process has started, then at that moment it can
be said that ‘obj’ has received :x, i.e. there is no more ‘receiving’
to be done, that part of the process is done, finito, fait accompli.
All that is left is the ‘apply’ process.

Going back to the code:

f = obj.resolve(:x) # 1
f.apply(1,2) # 2

During step 1, obj receives message :x and resolves the message into
a method definition which is captured and returned within f.

During step 2, the arguments 1 and 2 are applied to obj using the
method definition that was previously resolved.

If we switch the example back to the standard names we get:

m = obj.method(:x) # m is an instance of Method
m.call(1,2)

So to bring this back full circle. David pointed out that

m.receiver # obj

was ‘anomolous’ because m (an instance of Method) is all about
the ‘apply’ step of the process and not about the ‘resolve’
step of the process. In the ‘resolve’ step, obj is the
receiver of the message but that step is water under the bridge
once you’ve constructed an instance of Method.

And here is the real problem: We don’t have any accepted terminology
for the role of obj during the ‘apply’ process.

We never needed any because Method doesn’t have an accessor for
that data. It never needed to be named. And then Wolfgang posted
his message with the innocuous sounding title of “Minor Change
Proposal for Classes ‘Object’ and ‘Method’.”

Matz pointed out that all along it has been quite common to refer
to the object associated with ‘self’ as the implict or default
receiver. So why not use Method#receiver? It made sense to me.

The gotcha is that in:

def m1(a,b)
m2
end

self is the implicit receiver of the message :m2 but we can’t
really say anything at all about self with respect to :m1
because the question just isn’t meaningful from the
perspective of the execution of m1. It is only a meaningful
question from the perspective of how m1 came to be executed.

obj.m1(1,2) # obj is the receiver

or

m = obj.method(:m1) # obj receives and resolves :m1 here

m.call(1,2) # the empty argument list is applied
# to obj and the resolved method

I know I’m probably splitting hairs at this point but that is
exactly what Kernel#method does and I think it is exactly
what David was pointing out.

Here is yet another way to illustrate this hair splitting
that makes it blindingly obvious (to me at least) what
David was getting at:

a = [1,2]
b = [3,4]

fa = a.method(:first)
uf = fa.unbind
fb = uf.bind(b)
fb.call # 3

Question:
Where in this example does b receive the message :first?

Answer:
Nowhere, because b is never the receiver of the message :first.

I’m hoping that David is jumping up and down now saying

I told you so!

Taking all this into consideration, I think that Vincent F.'s
suggestion of Method#target is a pretty good one. The object
captured within an instance of Method is the ‘target’ of the
‘apply’ process I described above. It also suggests that when
talking about ‘self’ within an instance method we might use
terminology such as:

 self is the target of the method and is
 the receiver of any unqualified messages

I also realized that there are circumstances where ‘self’ is not
the target of any method at all but is still a receiver of
messages:

class X
attr :foo
end

Within a class block, self is the implicit or default receiver of
messages but is not the ‘target’ of any particular method.

Gary W.

On Jan 24, 2007, at 5:20 AM, Pit C. wrote:

Robert D. schrieb:

(… something like the following …)

ma = a.method(:x)
mb = ma.unbind.bind(b)

Robert, this is a nice counter example to what I’ve written. In
this case the object “b” surely hasn’t received anything. So I
guess its role is really only that of a #bound_object.

In going back through this thread I realized that I hadn’t understood
the
implications of Robert’s suggestion at the time. In my recent long post
about this I ‘rediscovered’ his example. So I certainly wasn’t the
first
person to point out this situation.

For me personally, I didn’t really understand David’s uneasiness about
Method#receiver until I realized that the ‘send/receive’ metaphor only
describes an early portion of the entire message dispatch process even
though it is almost always used (inaccurately in my mind) to describe
the entire process.

Gary W.

I don’t know where to put this message into the very large discussion
tree, so I
will put it here.

There is an argument against naming a method “receiver”, which returns
the
object which was bound to a method object.

Example >>>>>

class Otto
def hi
puts “‘Hi!’ from an ‘Otto’ instance (#{self.inspect})”
end
end

class Hugo < Otto
def hi
puts “‘Hi!’ from an ‘Hugo’ instance (#{self.inspect})”
end
end

o = Otto.new
h = Hugo.new
bo = o.method(:hi)
bh = bo.unbind.bind(h)

h.hi # => ‘Hi!’ from an ‘Hugo’ instance (#Hugo:0x2aea4dc)
bh.call # => ‘Hi!’ from an ‘Otto’ instance (#Hugo:0x2aea4dc)
bo.call # => ‘Hi!’ from an ‘Otto’ instance (#Otto:0x2aea478)

EoE >>>>>

In this example, the “Method” object “bh” contains (I temporary use this
wording
for this example) the object “h”, and the method “Otto#hi”, which can
be seen
in the output of “bh.call” - but - if ones sends the message “hi” to the
object
“h” the method “Hugo#hi” will be used (see output for “h.hi”).

This means, that for the object “h” contained in “Method” object “bh” a
message
“hi” will not end up in calling “Otto#hi”, because it finds “Hugo#hi”.

It is misleading to call “h” the “receiver” of a message, that leads to
the
invocation of “Otto#hi”, because this cannot be done by any message in
this example.

May be a different name is better to avoid confusion.

Wolfgang Nádasi-Donner

Sorry, I didn’t recognize, that this was already named. More than 90
posts in
this discussion are very much…

Wolfgang Nádasi-Donner

Hi!

I don’t know how you handle “Change Proposals” for Ruby. Implement them
silently
or write somewhere an announcement, so I try to summarize what happens,
as I
understood it.

Please correct me if I’m wrong, because I will report about the results
in the
german Ruby forum.

I include my proposal for class “UnboundMethod” here, because I think it
is
strongly related to this one.


As I understood, the will be some new methods available now or in the
near
future in the repository (or the nightly snapshot). I’m not sure about
the
chosen names, so please correct them.

==============
Class “Method”

Public instance Methods:

receiver

“receiver” returns the bound object of the method object. E.g. for “mo =
o.method(:m)” the expression “mo.receiver” will return “o”.

name

“name” returns the name of the method object. E.g. for “mo =
o.method(:m)” the
expression “mo.name” will return “:m” (symbol) or “‘m’” (string).

owner

“owner” returns the class which holds the method. E.g. for “mo =
o.method(:m)”
the expression “mo.owner” will return “c”, if the method “:m”, that is
bound to
“mo”, is defined in this class. If the class is an anonymous class, it
will be
handled correctly.

=====================
Class “UnboundMethod”

Public instance Methods:

name

“name” returns the name of the method object. E.g. for “mo =
o.method(:m)” the
expression “mo.name” will return “:m” (symbol) or “‘m’” (string).

owner

“owner” returns the class which holds the method. E.g. for “mo =
o.method(:m)”
the expression “mo.owner” will return “c”, if the method “:m”, that is
bound to
“mo”, is defined in this class. If the class is an anonymous class, it
will be
handled correctly.


Is it a correct summary. There are so many messages in the discussion,
that I
ended up in comfusion about the chosen names, sorry.

Wolfgang Nádasi-Donner