What's an object?

On Fri, Nov 12, 2010 at 1:31 PM, Xavier N. [email protected] wrote:

a → 2158937800 → “”
b → 2158934000 → “b”

because a and b store different values.
That’s actually what I meant: When passing the parameter the diagram
is correct. I do not see any reason why you claim the diagram
incorrect - for what the param passing semantics concerns - only
because Ruby gives you the freedom to reassign the param inside the
body of the method.
I wanted to express that this manipulation should not be used to prove
the correctness or incorectness of a given param passing model.
Clearer?

Cheers
R.

On Fri, Nov 12, 2010 at 3:56 PM, Robert D. [email protected]
wrote:

That’s actually what I meant: When passing the parameter the diagram
is correct. I do not see any reason why you claim the diagram
incorrect - for what the param passing semantics concerns - only
because Ruby gives you the freedom to reassign the param inside the
body of the method.

You think the parameter is an alias, and the local variable masks it
right? As if usage was pass-by-value but you couldn’t tell because of
that formality. Isn’t that convoluted? The spec says local variables
are created, why do you think a second local variable is later created?

I wanted to express that this manipulation should not be used to prove
the correctness or incorectness of a given param passing model.
Clearer?

I am not familiar with MRI but I’d swear this is what implements the
argument value copying of pass-by-value semantics (that’s from
vm_insnhelper.c in 1.9.2):

/* copy arguments */
for (i=0; i < (sp - rsp); i++) {
p_rsp[i] = rsp[i];
}

There, rsp has type VALUE*. If I understand the code correctly, that
in turn comes from copying the VALUEs in the argv argument of
vm_call0(). They are all plain assignments, we are just copying
pointers (or immediate values).

On Fri, Nov 12, 2010 at 5:15 PM, Robert D. [email protected]
wrote:

critisizing in the way of asking, I guess I was.
Let me try to draw a new diagram with words.

When we perform

x = Object.new

x does not hold an object. The variable holds a reference (my
interpretation of the verb “refers” in the spec). Say that reference
is in the case of MRI the VALUE 2158949260 (that is, a pointer).

So the diagram is inexact and I think I will revise it. The variable x
stores 2158949260, and it is the VM that gives you syntactic sugar
everywhere so that x.nil? follows the pointer for you to reach the
object to be able to send :nil? to it. The boxes in the diagram point
to a value, 1, while it would be more clear to put the 2158949260 in
the box. And perhaps a second box after it with the 1. (And an integer
is also exceptional in MRI, would use a different value).

That’d make the pass-by-value workflow more clear. When you invoke

def m(y)
end

passing x as argument, the VM constructs a new local variable y (local
to m), and initializes the variable with the value of x, which is
2158949260.

In this schema, x and y are unrelated variables, bound to unrelated
storage areas that happen to store the same integer value (a C
pointer).

Via the pointer they reach the same object, and that’s why you can
change the state of a mutable object. The same pointer reaches the
same object.

If Ruby was pass-by-reference x and y would point to the same box
containing 2158949260. And assignment would change that integer for
both variables.

Do you agree with the picture?

Hi, Josh

C.instance_method(‘meth’) == C.instance_method(‘meth’) # => true
I see. An UnboundMethod object represents a specific method
directly… Having the just reason that it is the Ruby’s concept, I
lost another reason why we should regard a method as an object.

Yet, UnboundMethods still have names

String.instance_method(“upcase”) # => #<UnboundMethod: String#upcase>
String.instance_method(“upcase”).name # => :upcase

I do not understand what the problem is. Did you think it is the
matter that an UnboundMethod object is still BOUND to the method name
in spite of “Unbound”, which is contained in the class name of the
UnboundMethod class? If you did, you need not be afraid of it.

The word “Unbound” in the class name means that an UnboundMethod
object is NOT BOUND to the RECEIVER.

On Fri, Nov 12, 2010 at 4:18 PM, Xavier N. [email protected] wrote:

On Fri, Nov 12, 2010 at 3:56 PM, Robert D. [email protected] wrote:

All you saying is completely clear, but does still not answer my
question.

Did you disagree with the diagram because it expresses an alias (I
fail to see that); or because of the fact that the arrow pointing to
the same object is “volatile”?

That was my question, sorry if I was not clear 'nuff or was too
critisizing in the way of asking, I guess I was.

Cheers
R.

On Fri, Nov 12, 2010 at 5:33 PM, Xavier N. [email protected] wrote:

Do you agree with the picture?
Completely!
I agree that we have pass by value. My question is, why do you dislike
this representation for it

def meth a

meth(b)

a —+
|
±-----> An Object
|
b—+

I thought it was making things quite clear
Maybe one should add that after

b = 42

the picture changes.

R.

On Fri, Nov 12, 2010 at 04:59:02PM +0900, Robert K. wrote:

irb(main):001:0> foo = 1.method ‘+’
=> #<Method: Fixnum#+>
irb(main):002:0> foo[3]
=> 4

which is pretty close to foo(3).

You appear to be confusing syntax with semantics here. Sure, brackets
look a little like parentheses – but they aren’t, and they mean very,
very different things in Ruby.

That’s because a “method object” is not a method; it is a proc that wraps
the method and its scope context.

Exactly.

So . . . you agree with me.

On Fri, Nov 12, 2010 at 04:29:28PM +0900, Josh C. wrote:

Here’s a thought experiment for you:

Why should you be able to do foo(3) ? That would require completely changing
the way Ruby is interpreted. I suspect this idea comes from less OO
languages like JavaScript and Python. In Ruby, you can’t do that, because if
foo is the object, then you interact with it by invoking methods. (3) isn’t
a method, it’s an argument, so we need to define a method that will invoke
our method object. So we define #call and use .call(3)

Why should you be able to do puts(3), if you think we should not be able
to do foo(3)?

You should be able to do foo(3) because you seem to think that the
method
and the object are the same thing. In order to get the object to which
you can send messages, though, you need to do something like I did: get
it out of the “method” method as a return value. What the faiure of
foo(3) to work shows is that when you have a method object you no
longer have a method that can be invoked by sending its name as a
message
to an object. Instead, you have to send a message to it. This
demonstrates that when you interact with foo, you’re no longer
interacting with the method itself.

You’re confusing the method object with the method itself, again. The
reason you should be able to do foo(3) is that, if the method is the
object, you should be able to treat the object like a method. Since you
cannot just call the method object the same way you would call the
object, the method object and the method are obviously not the same
thing.

I’ll try again:

~> irb
irb(main):001:0> puts(3)              # treat puts like a method
3
=> nil
irb(main):002:0> puts.call(3)         # treat puts like an object

NoMethodError: undefined method `call' for nil:NilClass
        from (irb):2
        from :0
irb(main):003:0> foo = Kernel.method('puts')
=> #<Method: Kernel.puts>
irb(main):004:0> foo(3)               # treat foo like a method
NoMethodError: undefined method `foo' for main:Object
        from (irb):4
        from :0
irb(main):005:0> foo.call(3)          # treat foo like an object
3
=> nil

Is it clear what’s happening hear?

token               type    treated like    status

puts(3)             method  method          success

puts.call(3)        method  object          failure

foo(3)              object  method          failure

foo.call(3)         object  object          success

I don’t know how it can get any clearer than that.

The fact that you have to send it a message shows it is an object,
which is easy to see, since at this point, foo is an object. It is an
instance of Method.

As you can see, this has absolutely nothing to do with what my example
code demonstrated.

I think it would be much more convincing to me that there is any merit
to this model if you could show me, for example, how you interact with
it in its non-object form.

See above.

Outside of methods, I wish everything was an object. Alas, bare
keywords
like “if” and “while” are not objects in Ruby. I have no strong feeling
one way or the other at this point about whether methods should or
should
not be objects – but, just like bare keywords, the way they actually
“behave” makes it clear to the discerning observer that they are not
in
fact objects.

Maybe I have a slight advantage because I have spent so much time in my
life on things like truth tables and deductive philosophy. I don’t know
why I saw this so quickly and you insist that it is not true. It is,
though. Sorry.

Just in case another perspective might help, I’ll try one more way of
saying the same thing:

Objects respond to methods. Methods return objects. Objects do not
“return” anything except their own identifiers, and methods do not
respond to messages.

Sorry, I made a mistake.

error:

Having the just reason that it is the Ruby’s concept, I lost
another reason why we should regard a method as an object.

corrected:
Having the just reason that it is the Ruby’s concept, I lost another
reason why we should NOT regard a method as an object.

On Fri, Nov 12, 2010 at 10:35 PM, Chad P. [email protected] wrote:

Why should you be able to do puts(3), if you think we should not be able
to do foo(3)?

Because puts(3) is shorthand for “send the object ‘Kernel’ the message
‘puts’ with the parameter ‘3’” but foo(3) is shorthand for “send the
object
‘foo’ no message at all with the argument 3” That doesn’t work because
it is
not consistent with Ruby’s object model.

In other words, the difference is this:

Kernel.send “puts” , 3
foo.send “” , 3

They may look the same the way you formatted their syntax, but they are
completely different.

Putting (3) after puts is not what invoked it. Sending it to the object
Kernel is what invoked it. Likewise, putting (3) after foo will not
invoke
foo, rather, sending call to the object foo will invoke it. I can’t
think of
any way to reconcile such a belief with anything anywhere in Ruby, and
your
puts example only appears to be an exception because you formatted it
deceptively.

From your table, its not that puts.call(3) and foo(3) fail to work, its
that
they don’t even make sense. puts is invoked, it returns a value. You
aren’t
sending call to puts, you are sending it to nil, the object that puts
returns. You are just using tricks of syntax to be ambiguous. Make
it Kernel.puts().call(3) and it is explicit. Make it self.foo(3) and it
is
explicit, it is a message to self, not to foo.

On Fri, Nov 12, 2010 at 7:04 PM, Robert D. [email protected]
wrote:

Completely!

Aaahhh, perfect :).

  +------> An Object
  |

b—+

I thought it was making things quite clear
Maybe one should add that after

b = 42

the picture changes.

Because I think the object at the end of the arrow may be misleading
for explaining call semantics.

Problem is those arrows do not mean storage, in my view we really have
two types of arrows. First arrow is

the variable a _stores_ the reference 2158949300

That’s what matters for call semantics, what does the variable hold.
It does not matter whether that integer is a pointer, and if it is a
pointer what does it point to.

A second arrow of a different type points to an object from the pointer
box

2158949300 _refers to_ "say, some string"

That information is helpful and gives the whole picture about how
method invocation relates to objects, but it is in my view beyond call
semantics.

In that sense the diagrams of my post are not clear enough for
depicting what the post wants to explain, I think I’ll revise it to
include the reference/pointer boxes.

– fxn

PS: I have to say that those arrows and boxes match the observed
behavior and MRI implementation, but the spec as far as I can tell
does not imply them with 100% confidence in my opinion.

I do believe that’s what the spec wants to specify, but the word
“reference” is not used, and the verb “copy” does not appear either.
My interpretation is that the first is there via the verb “refers”,
and the fact that variables are not objects. And that in method
invocation “copy” is obviated because we are dealing with pointers and
the mere described assignment is enough. I’ve written to Matz about
this.

Hi,

In message “Re: what’s an object?”
on Sat, 13 Nov 2010 15:13:54 +0900, Xavier N. [email protected]
writes:

|PS: I have to say that those arrows and boxes match the observed
|behavior and MRI implementation, but the spec as far as I can tell
|does not imply them with 100% confidence in my opinion.
|
|I do believe that’s what the spec wants to specify, but the word
|“reference” is not used, and the verb “copy” does not appear either.
|My interpretation is that the first is there via the verb “refers”,
|and the fact that variables are not objects. And that in method
|invocation “copy” is obviated because we are dealing with pointers and
|the mere described assignment is enough. I’ve written to Matz about
|this.

So you guys seem to agree with the basic concept. From CRuby
implementation stand point, variables are fundamentally pointer to the
object (region within a heap), with some exceptions of immediate
values. In that sense, Xavier’s description is correct. But we
haven’t choose to use those terms in the standard description, just
because the spec should not assume particular implementation detail.
On some alternative implementation, the object might be represented by
mere number, or combination of pointer values.

          matz.

On Sat, Nov 13, 2010 at 10:09 AM, Yukihiro M.
[email protected] wrote:

|and the fact that variables are not objects. And that in method
On some alternative implementation, the object might be represented by
mere number, or combination of pointer values.

Excellent.

Then, at the spec level, we can assume that conceptually variables
hold references, whose implementation may vary, and that they refer to
objects. It belongs to the public contract of the language that a
variable does not store an object, and that v.foo asks the interpreter
to
send a “foo” message to the object the variable v refers to.

I mean, that’s the real and public contract. One can speak informally
about sending a message to v, but when you need to be rigorous about
the formalities of the language (eg in the context of this thread to
explain why Ruby has pass-by-value semantics) the reference in v has
an unspecified implementation, but it is conceptually explicit.

On Sat, Nov 13, 2010 at 7:13 AM, Xavier N. [email protected] wrote:

On Fri, Nov 12, 2010 at 7:04 PM, Robert D. [email protected] wrote:

Completely!

Aaahhh, perfect :).

I guess, I eventually understand. It was not the structure of the
diagram, that bothered you but the unclear/undefined/missdefined
semantics of the —>.
You see I understand quickly, if you explain a very long time, thanks.

Robert

On Sat, Nov 13, 2010 at 03:23:13PM +0900, Josh C. wrote:

not consistent with Ruby’s object model.

In other words, the difference is this:

Kernel.send “puts” , 3
foo.send “” , 3

The claim was that foo is just the “object” puts, though, which means
that should actually look like this:

Kernel.send "puts" , 3
Kernel.send "foo" , 3

. . . if the method and the object are the same thing. The fact they
don’t work that way just shows that they method and the object are not
the same thing – that the method puts is not an object as claimed.

They may look the same the way you formatted their syntax, but they are
completely different.

The fact they are completely different is my point. One is an object.
The other is a method. Ne’er the twain shall meet.

Putting (3) after puts is not what invoked it. Sending it to the object
Kernel is what invoked it. Likewise, putting (3) after foo will not invoke
foo, rather, sending call to the object foo will invoke it. I can’t think of
any way to reconcile such a belief with anything anywhere in Ruby, and your
puts example only appears to be an exception because you formatted it
deceptively.

I don’t even know what you’re trying to say here that disagrees with
anything I was saying. My question was rhetorical, because I already
knew (and was making the point) that foo (the object) and puts (the
method) are not the same thing.

From your table, its not that puts.call(3) and foo(3) fail to work, its that
they don’t even make sense. puts is invoked, it returns a value. You aren’t
sending call to puts, you are sending it to nil, the object that puts
returns. You are just using tricks of syntax to be ambiguous. Make
it Kernel.puts().call(3) and it is explicit. Make it self.foo(3) and it is
explicit, it is a message to self, not to foo.

Of course, they don’t make sense. That’s my point. One is a method,
the
other an object. If the method was an object, you’d be able to send
it
messages to invoke methods. You can’t – as you pointed out. Thank you
for making my point for me.