what's an object?

X

Xavier Noria

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 = rsp;
}

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

Robert Dober

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

Xavier Noria

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.

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?
 
Y

Y. NOBUOKA

Hi, Josh
cmeth1 = meth_obj1.unbind
cmeth2 = meth_obj2.unbind

cmeth1 == cmeth2 # => true
cmeth1 == C.instance_method('meth') # => true
cmeth2 == C.instance_method('meth') # => true
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.
I will concede that you have a spec which says that a method is not an
object. However, I do so with reserve, because this same spec, in this same
paragraph it says "A method has one or more (when aliased) names associated
with it. An association between a name and a method is called a method
binding . When a name N is bound to a method M, N is called the name of the
binding, and M is called the value of the binding. A name bound to a method
is called the method name . A method can be invoked on an object by
specifying one of its names. The object on which the method is invoked is
called the receiver of the method invocation."

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

Robert Dober

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

Y. NOBUOKA

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

Xavier Noria

Completely!

Aaahhh, perfect :).
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 ---+
=C2=A0 =C2=A0 =C2=A0 |
=C2=A0 =C2=A0 =C2=A0 +------> An Object
=C2=A0 =C2=A0 =C2=A0 |
b---+

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

b =3D 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.
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

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

Xavier Noria

In message "Re: what's an object?"
=C2=A0 =C2=A0on Sat, 13 Nov 2010 15:13:54 +0900, Xavier Noria <fxn@hashre=
f.com said:
|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. =C2=A0From CRuby
implementation stand point, variables are fundamentally pointer to the
object (region within a heap), with some exceptions of immediate
values. =C2=A0In that sense, Xavier's description is correct. =C2=A0But w= e
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.

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

Robert Dober

Aaahhh, perfect :).
<snip>
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top