No variable ever *is* an object in Ruby. Variables *reference* objects!
Now that's a different, or at least clearer, statement. And it fits
with what I know.
Yes. It's important when you compare "pass by value" or "pass by
reference" in other languages. In ruby, everything is "pass by value",
and each value is a reference to an object - even integers.
IMO this is a *huge* logical simplification over languages like perl
(scalar? array? array ref? list? hash? hash ref? filehandle? typeglob?
subroutine? Deal with them all differently)
In ruby, a local variable is not an object, and as such you can never
obtain a "reference" to it.
def foo(x)
x << " world"
end
a = "hello"
foo(a)
a is passed by value, so the method call foo(a) can never affect the
value of a - it must remain pointing to the same object after the call.
However, if the object is mutable, it can cause it to change state
(using the << method in the example above)
> >
> > Alex said everything is an object--including an instance of a class,
> > the class itself, its methods. I agree up until he mention methods as
> > objects. I don't think that can be demonstrated. For instance, we
> > cannot get the object_id of a method. '+.object_id' doesn't work. So,
> > I don't agree that methods are objects.
> >
> 1.method('+').object_id
1.method('+') is not the same as 1.+, so your example does not prove + is
a method. The object ID you get with 1.method('+').object_id is actually
the object ID of the object that is returned by the method "method" when
it is passed an argument of the string "+". That is not the same thing
as an object ID for the + method itself.
Here's a thought experiment for you:
If + is an object, and 1.method('+') returns that object so that you can
get its object ID with 1.method('+').object_id, this should work:
> foo = 1.method('+')
> foo(3)
4
>
Fire up irb and try it, now. It doesn't work.
Instead, if you want to use it, you need to do this:
> foo = 1.method('+')
> foo.call(3)
4
>
That's because a "method object" is not a method; it is a proc that wraps
the method and its scope context.
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)
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.
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.
It's a question of the mental model, but to my memory even Matz's mental
model does not correspond to yours - i remember seeing a presentation
where he explicitly said that methods were not objects, I can find it
soon hopefully and link it here.
Nonetheless, the book "The Ruby Programming Language" which was
co-written
by Matz has this to say on the matter:
"Methods are a fundamental part of Ruby's syntax, but they are not
values that Ruby programs can operate on. That is, Ruby's methods are
not objects in the way that strings, numbers, and arrays are. It is
possible, however, to obtain a Method object that represents a given
method, and we can invoke methods indirectly through Method objects."
Hi, John. I suspect that Matz' mental model views methods like this because
he is implementing MRI. For him, this is a necessary model. Aside from
object_id, I can't think of any situation outside of the C code where this
would ever be a useful way of thinking. I would expect that most of the time
it will just make it more difficult for you to reason about your code,
because your mental model is more complicated due to having have one more
exception for where Ruby behaves unexpectedly that you have to reason
through.
Right after Matz' quote you gave, he says "Blocks, like methods, are not
objects that Ruby can manipulate." But on this topic, I am very much with
Yehuda Katz who says
"In a number of places, it is possible to imbue Ruby semantics with mental
models that reflect the actual Ruby implementation, or the fact that it’s
possible to imagine that a Ruby object only springs into existence when it
is asked for.
However, these mental models require that Ruby programmers add non-objects
to the semantics of Ruby, and requiring contortions to explain away Ruby’s
own efforts to hide these internals from the higher-level constructs of the
language. For instance, while Ruby internally wraps and unwraps Procs when
passing them to methods, it makes sure that the Proc object attached to a
block is always the same, in an effort to hide the internal details from
programmers.
As a result, explaining Ruby’s semantics in terms of these internals
requires contortions and new constructs that are not natively part of Ruby’s
object model, and those explanations should be avoided."(
)
That is exactly what I feel is happening here.
···
On Thu, Nov 11, 2010 at 9:05 PM, Chad Perrin <code@apotheon.net> wrote:
On Thu, Nov 11, 2010 at 04:51:46PM +0900, Josh Cheek wrote:
> On Wed, Nov 10, 2010 at 11:55 PM, timr <timrandg@gmail.com> wrote:
On Thu, Nov 11, 2010 at 9:14 PM, John Mair <jrmair@gmail.com> wrote:
Fair enough. The link even cites the Ruby spec to indicate that
methods, technically, are not/do not have to be an object.
However, there is much to support that it is not at all a conceptual
error to consider a method an object, even if the technical
implementation is different.
Consider that Ruby is a dynamically-typed language, frequently described
as duck-typed. If a Method object has attributes, such as #arity and
even #class, and methods like #call or #to_s, it sure looks like an
object to me. Also consider that Ruby by design is intended not to get
in the programmer's way, the way a language like PHP or Perl might,
because of its dynamic features and flexibility.
One does not need to know the internal details - such as "the 4th and
5th paragraphs of Section 6.1 of the Ruby Language Specification (lines
29-34 and 1-5 on pages 5 and 6)" - to be an effective programmer in
Ruby. Does knowing those details give a programmer more options and a
better understanding of the source-to-machine connection and the
physical operation of their code? Absolutely. But does assuming that
methods look like an object, and act like an object, and ignoring the
underlying mechanisms (the black box effect), make a Ruby programmer
less capable or likely to introduce bugs? Probably not.
In fact, I would reference Russ Olsen's excellent "Design Patterns in
Ruby" at this point. In Ch.2 of a very heavily abstracted, conceptual
text (yet also quite practical, but I digress...), he states explicitly
that everything is an object. He also says that, in the case of numeric
assignment like 'x = 44', that "...x receives a reference to an object
that happens to represent the number after 43." That seems to be
remarkably similar to what happens in the case of the Method class,
where the user doesn't really need to know what's going on, and can
readily accomplish their task without concerning themselves with how 44
is referenced or represented or how Method wraps a method.
Great knowledge for interpreter hackers, but would assuming methods are
objects and getting on with it be problematic? Would not knowing that
subtraction is accomplished through addition also be problematic?
I see there's some later posts now, so I'll hit send now.
Alex Stahl | Sr. Quality Engineer | hi5 Networks, Inc. | astahl@hi5.com
On Thu, 2010-11-11 at 01:51 -0600, Y. NOBUOKA wrote:
> Not that I know the internals of the language well enough to debate the
> internal representation of a method, everything I've read suggests that,
> at a conceptual level, they can be regarded as such. Otherwise, how
> would we reconcile this description from the Method class link?
> (http://ruby-doc.org/core/classes/Method.html\)
>
> meth == other_meth => true or false
> "Two method objects are equal if that are bound to the same object and
> contain the same body"
>
> Couldn't methods be considered specialized proc objects bound to a
> particular instantiation of an object?
A Method object (= an instance of the Method class) is an object. But
it is not a method. It can be considered as a wrapper of the method
which is bound to an object.
We should think that a Method object is a thing that is different from
a method.
---
Methods are a fundamental part of Ruby's syntax, but they are not
values that Ruby programs can operate on. That is, Ruby's methods are
not objects in the way that strings, numbers, and arrays are. It is
possible, however, to obtain a Method object that represents a given
method, and we can invoke methods indirectly through Method objects.
--- From "The Ruby Programming Language" [ http://www.amazon.com/dp/0596516177/ ]
I agree with Yehuda too. But I do not feel the case of Method
objects/methods is analogous to the case of blocks/procs. The
fundamental reason is that a very crucial point of Yehuda's argument is
that when you on-pass the block it has the same object_id; in fact in
Yehuda's article this point is mentioned multiple times culiminating in
this statement:
"You can tell that blocks are not being semantically wrapped and
unwrapped
because blocks passed along via & share the same object_id across
methods."
This semantic wrapping/unwrapping on the other hand is EXACTLY what's
happening in the case of methods and method objects. In other words,
what is happening with methods/method objects is precisely what Yehuda
was arguing was *not* happening with blocks/procs.
Yehuda's argument *would* apply to methods/method objects if the
object_id remained the same across multiple calls to the method method.
Read what he wrote again, the persistent object_id is a big part of his
argument.
To try to maintain the mental model that a method is really an object is
actually impossible if the object keeps changing
It is not impossible in the case of blocks/procs however, as the
object_id remains the same.
> >
> > Alex said everything is an object--including an instance of a class,
> > the class itself, its methods. I agree up until he mention methods as
> > objects. I don't think that can be demonstrated. For instance, we
> > cannot get the object_id of a method. '+.object_id' doesn't work. So,
> > I don't agree that methods are objects.
> >
> 1.method('+').object_id
1.method('+') is not the same as 1.+, so your example does not prove + is
a method. The object ID you get with 1.method('+').object_id is actually
the object ID of the object that is returned by the method "method" when
it is passed an argument of the string "+". That is not the same thing
as an object ID for the + method itself.
Here's a thought experiment for you:
If + is an object, and 1.method('+') returns that object so that you can
get its object ID with 1.method('+').object_id, this should work:
> foo = 1.method('+')
> foo(3)
4
>
Fire up irb and try it, now. It doesn't work.
Instead, if you want to use it, you need to do this:
>
> 1.method('+') is not the same as 1.+, so your example does not prove + is
> a method. The object ID you get with 1.method('+').object_id is actually
> the object ID of the object that is returned by the method "method" when
> it is passed an argument of the string "+". That is not the same thing
> as an object ID for the + method itself.
>
> Here's a thought experiment for you:
>
> If + is an object, and 1.method('+') returns that object so that you can
> get its object ID with 1.method('+').object_id, this should work:
>
> > foo = 1.method('+')
> > foo(3)
> 4
> >
>
> Fire up irb and try it, now. It doesn't work.
>
> Instead, if you want to use it, you need to do this:
>
> > foo = 1.method('+')
> > foo.call(3)
> 4
> >
>
> That's because a "method object" is not a method; it is a proc that wraps
> the method and its scope context.
>
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
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
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.
···
On Fri, Nov 12, 2010 at 04:29:28PM +0900, Josh Cheek wrote:
On Thu, Nov 11, 2010 at 9:05 PM, Chad Perrin <code@apotheon.net> wrote:
> On Thu, Nov 11, 2010 at 04:51:46PM +0900, Josh Cheek wrote:
Did you recognize the difference between a method and a Method object?
They are quite different. A Method object is a object which wrap a
method that is bound to a specific object.
One does not need to know the internal details - such as "the 4th and
5th paragraphs of Section 6.1 of the Ruby Language Specification (lines
29-34 and 1-5 on pages 5 and 6)" - to be an effective programmer in
Ruby.
Yes. I agree that one does not need to know the internal details.
However, the difference between a Method object and a method is not
the internal details.
The relation between a method and a Method object in Ruby can be
compared to the relation between a function and a structure which have
a function pointer in C.
--- in C
/**
* here define a structure which have a function pointer
* this structure is equivalent to the Method class in Ruby
*/
typedef struct {
int (*pointer)( int arg );
} Fuction;
/**
* here define a function to obtain a Function structure
*/
Function *obtain_Function( int (*pointer)( int arg ) ) {
Function *f = malloc( sizeof( Function ) );
f->pointer = pointer;
return f;
}
/* here is a function */
int func( int arg ) {
return arg * 2;
}
/* obtain the Function structure which wrap the function *func* */
Function *func_obj = obtain_Function( func );
···
---
--- in Ruby
/* here is a method */
def meth( arg )
return arg * 2;
end
/* obtain the Method object which wrap the method *meth* */
meth_obj = method( :meth )
---
Can you recognize the difference between a method and a Method object?
In C, the Function structure is exactly a structure, while the
function *func* is not. In Ruby, similarly, the Method object is a
object and the method *meth* is not.
I think that Ruby users need not know how a Method object wraps a
method, but they should know the fact that a Method object wraps a
method and a method is not a object.
Point is a holds a reference, and that one can't be changed. You can
change the state of the object it points to if it is mutable, but the
string object is the same when the method returns because Ruby has
pass by value semantics.
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:59:02PM +0900, Robert Klemme wrote:
> On Thu, Nov 11, 2010 at 9:05 PM, Chad Perrin <code@apotheon.net> wrote:
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 10:35 PM, Chad Perrin <code@apotheon.net> wrote:
Why should you be able to do puts(3), if you think we should not be able
to do foo(3)?
Disclaimer: I seem to be in a crabby mood this morning. I went back over it
(twice) and tried to take out things that were unfriendly, sorry if I missed
anything.
/* obtain the Function structure which wrap the function *func* */
Function *func_obj = obtain_Function( func );
That isn't what you do in Ruby. In Ruby, you don't pass the function (or
function pointer in this case), you pass a String or Symbol.
So this example is not consistent with what Ruby does, doesn't have any
explanatory power (that I can see, though I don't write C extensions), and
makes everything more complicated.
Here is an alternative model: In Ruby, everything is an object. Methods are
objects, hence the method class. class Method - RDoc Documentation But you can't directly access
them, because Ruby doesn't make you use parentheses. So trying to access the
method directly looks to the interpreter like you want to invoke the method,
since that is pretty much always what you want to do. But every now and
then, you want to actually get the method, and so Ruby gives you a getter
method that knows how to do that, and it's aptly named "method".
In C, that looks something like
#include <stdio.h> #include <string.h>
typedef struct {
char* name;
int (*pointer)( int arg );
} Method;
int twice( int arg ) { return arg * 2; }
int thrice( int arg ) { return arg * 3; }
Method* method( char* name ) {
int i;
for( i = 0 ; i < sizeof(internal_mlist)/sizeof(Method) ; ++i )
if( !strcmp( internal_mlist[i].name , name ) )
return &internal_mlist[i];
return NULL;
}
int main( ) {
method("twice");
method("thrice");
return 0;
}
For a longer version that is more in line with my mental model
I think that Ruby users need not know how a Method object wraps a
method, but they should know the fact that a Method object wraps a
method and a method is not a object.
Why? Is that even a Ruby thing? It seems so out of place to me that I would
assume it is an MRI implementation detail. Do the other Rubies do it that
way? If so, is it just for efficiency where they are all objects as soon as
we need them to be, but keep it lazy and don't bother turning them into
objects until such time as we know we need it?
You guys were talking about a spec earlier, the site is apparently down
right now, but I downloaded the source from github ( https://github.com/rubyspec/rubyspec\), trying to find something on this.
Maybe I'm not looking in the right spot (I searched for /\.method[^_s]/) but
I didn't see anything like this in there.
···
On Thu, Nov 11, 2010 at 6:10 AM, Y. NOBUOKA <nobuoka@r-definition.com>wrote:
On Thu, Nov 11, 2010 at 8:59 AM, Brian Candler <b.candler@pobox.com> wrote:
Yes. It's important when you compare "pass by value" or "pass by
reference" in other languages. In ruby, everything is "pass by value",
and each value is a reference to an object - even integers.
I think we settled on the phrase "object reference" last time this came up.
> Hi Brian,
>
> I just tested what you said, the result is opposite, a is changed.
Point is a holds a reference, and that one can't be changed. You can
change the state of the object it points to if it is mutable, but the
string object is the same when the method returns because Ruby has
pass by value semantics.
Can we just call it "pass by object reference". Calling it "pass by value"
is so confusing, because in the code below, it sounds like you are talking
about the first function call when you are actually talking about the
second. And quite frankly, I think some people swap these definitions out
with each other. In your blog, your picture of pass by reference is actually
what I am calling pass by object reference, which you call pass by value (so
you give that as an example of not being what Ruby does, when it actually
is). It makes the entire discussion extremely difficult since different
things have the same name, and people's positions are shifting all the time.
#include <stdio.h>
typedef struct { int value; } Number;
void pass_by_value( Number number ) {
printf("Pass by value: %d\n" , number.value );
}
void pass_by_object_reference( Number *number ) {
printf("Pass by object reference: %d\n" , number->value );
}
void pass_by_reference( Number **number ) {
printf("Pass by reference: %d\n" , (*number)->value );
}
int main( ) {
Number object = { 12 };
Number* variable = &object; /* in Ruby you interact with objects through
variables that reference them */
pass_by_value(*variable);
pass_by_object_reference(variable);
pass_by_reference(&variable);
return 0;
}
@Josh,
I agree with Yehuda too. But I do not feel the case of Method
objects/methods is analogous to the case of blocks/procs. The
fundamental reason is that a very crucial point of Yehuda's argument is
that when you on-pass the block it has the same object_id; in fact in
Yehuda's article this point is mentioned multiple times culiminating in
this statement:
"You can tell that blocks are not being semantically wrapped and
unwrapped
because blocks passed along via & share the same object_id across
methods."
This semantic wrapping/unwrapping on the other hand is EXACTLY what's
happening in the case of methods and method objects. In other words,
what is happening with methods/method objects is precisely what Yehuda
was arguing was *not* happening with blocks/procs.
Yehuda's argument *would* apply to methods/method objects if the
object_id remained the same across multiple calls to the method method.
Read what he wrote again, the persistent object_id is a big part of his
argument.
To try to maintain the mental model that a method is really an object is
actually impossible if the object keeps changing
It is not impossible in the case of blocks/procs however, as the
object_id remains the same.
Okay. I guess I will agree to disagree. For me, that is a lot of exceptional
cases to add to my understanding of the language just to explain a different
object id (which almost feels like an oversight to me, but I checked, and
the spec code doesn't address that), and I am going to opt for the elegant
model where everything is an object until such time as it becomes a
hindrance. If you don't wish to do that, I won't tell you to, though I don't
think it's a good idea to teach it to newcomers, poor Eva's head must be
spinning
···
On Fri, Nov 12, 2010 at 1:32 AM, Xavier Noria <fxn@hashref.com> wrote:
On Friday, November 12, 2010, zuerrong <zuerrong@gmail.com> wrote:
On Fri, Nov 12, 2010 at 1:51 AM, John Mair <jrmair@gmail.com> 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
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.
···
On Sat, Nov 13, 2010 at 03:23:13PM +0900, Josh Cheek wrote:
On Fri, Nov 12, 2010 at 10:35 PM, Chad Perrin <code@apotheon.net> wrote:
It's a question of the mental model, but to my memory even Matz's mental
model does not correspond to yours - i remember seeing a presentation
where he explicitly said that methods were not objects, I can find it
soon hopefully and link it here.
Nonetheless, the book "The Ruby Programming Language" which was
co-written
by Matz has this to say on the matter:
"Methods are a fundamental part of Ruby's syntax, but they are not
values that Ruby programs can operate on. That is, Ruby's methods are
not objects in the way that strings, numbers, and arrays are. It is
possible, however, to obtain a Method object that represents a given
method, and we can invoke methods indirectly through Method objects."
Disclaimer: I seem to be in a crabby mood this morning. I went back over
it
(twice) and tried to take out things that were unfriendly, sorry if I
missed
anything.
On Thu, Nov 11, 2010 at 6:10 AM, Y. NOBUOKA > <nobuoka@r-definition.com>wrote:
/* obtain the Function structure which wrap the function *func* */
Function *func_obj = obtain_Function( func );
That isn't what you do in Ruby. In Ruby, you don't pass the function (or
function pointer in this case), you pass a String or Symbol.
So this example is not consistent with what Ruby does, doesn't have any
explanatory power (that I can see, though I don't write C extensions),
and
makes everything more complicated.
Here is an alternative model: In Ruby, everything is an object. Methods
are
objects, hence the method class. class Method - RDoc Documentation But you can't directly
access
them, because Ruby doesn't make you use parentheses. So trying to access
the
method directly looks to the interpreter like you want to invoke the
method,
since that is pretty much always what you want to do. But every now and
then, you want to actually get the method, and so Ruby gives you a
getter
method that knows how to do that, and it's aptly named "method".
In C, that looks something like
#include <stdio.h> #include <string.h>
typedef struct {
char* name;
int (*pointer)( int arg );
} Method;
int twice( int arg ) { return arg * 2; }
int thrice( int arg ) { return arg * 3; }
I think that Ruby users need not know how a Method object wraps a
method, but they should know the fact that a Method object wraps a
method and a method is not a object.
Why? Is that even a Ruby thing? It seems so out of place to me that I
would
assume it is an MRI implementation detail. Do the other Rubies do it
that
way? If so, is it just for efficiency where they are all objects as soon
as
we need them to be, but keep it lazy and don't bother turning them into
objects until such time as we know we need it?
You guys were talking about a spec earlier, the site is apparently down
right now, but I downloaded the source from github ( https://github.com/rubyspec/rubyspec\), trying to find something on this.
Maybe I'm not looking in the right spot (I searched for /\.method[^_s]/)
but
I didn't see anything like this in there.
On Thu, Nov 11, 2010 at 8:59 AM, Brian Candler <b.candler@pobox.com> > wrote:
Yes. It's important when you compare "pass by value" or "pass by
reference" in other languages. In ruby, everything is "pass by value",
and each value is a reference to an object - even integers.
I think we settled on the phrase "object reference" last time this came
up.
Can we just call it "pass by object reference". Calling it "pass by value"
I see no need. The stuff is pretty simple. Variables in Ruby and Java
hold references, their spec say that, it is not a mental model of mine.
(In the case of Java they can also store primitive values, you know.)
References are opaque, but it is known that whatever they are, that's
what variables hold. And the content of the variable is copied
when there's a method call.
void pass_by_object_reference( Number *number ) {
printf("Pass by object reference: %d\n" , number->value );
}
In the case of C there's no room for interpretation either. And it is
even more transparent than in Ruby because pointers are data types. So
that number parameter holds a data value which is a pointer, that one
isn't even opaque.
When the function is invoked the pointer is *copied*, that is, an integer
value is copied and linked to a local variable. The exact same thing
happens if the parameter is int i.
The pointer value is copied into the number variable (pass by value).
You can be certain the caller sees the exact same pointer when
the function call returns.
···
On Fri, Nov 12, 2010 at 9:38 AM, Josh Cheek <josh.cheek@gmail.com> wrote:
/* obtain the Function structure which wrap the function *func* */
Function *func_obj = obtain_Function( func );
That isn't what you do in Ruby. In Ruby, you don't pass the function (or
function pointer in this case), you pass a String or Symbol.
I wanted to show the simple example, so I used the function pointer.
My example, however, was not good. Sorry.
Here is an alternative model: In Ruby, everything is an object. Methods are
objects, hence the method class. class Method - RDoc Documentation But you can't directly access
them, because Ruby doesn't make you use parentheses. So trying to access the
method directly looks to the interpreter like you want to invoke the method,
since that is pretty much always what you want to do. But every now and
then, you want to actually get the method, and so Ruby gives you a getter
method that knows how to do that, and it's aptly named "method".
We can think a method is an object but we can't touch it, as you said.
Then, why do we need to think that it is an object? We need not
consider a method as an object, because we cannot access the object
which represents the specific method even if a method is an object.
If you think that the Method object represents the specific method
directly, the idea is not good. The Method object knows not only the
method but also the receiver, so there are many different Method
objects that refer to the same method. Please see the following
example.
···
---
class C
# the method *meth* is defined in a class *C*
def meth
puts "aaa"
end
end
c1 = C.new
# we can get the Method object which refers to the method C#meth
meth_obj1 = c1.method :meth
# this object knows the receiver
meth_obj1.receiver == c1 #=> true
# other Method object which refers to the same method
meth_obj2 = C.new.method :meth
# both meth_obj1 and meth_obj2 refer to the method C#meth,
# but these objects is not equal
meth_obj1 == meth_obj2 #=> false
---
In the example, we can see these Method objects don't represent the
method C#meth directly. Then, how do we obtain the object which
represents the method C#meth directly? No, we can't. There is no way.
That is why we cannot identify the Method object with the specific method.
I think that Ruby users need not know how a Method object wraps a
method, but they should know the fact that a Method object wraps a
method and a method is not a object.
Why? Is that even a Ruby thing? It seems so out of place to me that I would
assume it is an MRI implementation detail. Do the other Rubies do it that
way? If so, is it just for efficiency where they are all objects as soon as
we need them to be, but keep it lazy and don't bother turning them into
objects until such time as we know we need it?
Yes. It is a Ruby's concept that a method is not an object.
When the function is invoked the pointer is *copied*, that is, an integer
value is copied and linked to a local variable. The exact same thing
happens if the parameter is int i.
The exact same thing also happens with a reference (at least in C++, I don't
know anything about Perl).
The pointer value is copied into the number variable (pass by value).
You can be certain the caller sees the exact same pointer when
the function call returns.
Please re-read your blog with this in mind, since what you right here in
this quote are calling "pass by value" you, in your blog, call
"pass-by-reference".
In the example, we can see these Method objects don't represent the
method C#meth directly. Then, how do we obtain the object which
represents the method C#meth directly? No, we can't. There is no way.
>> I think that Ruby users need not know how a Method object wraps a
>> method, but they should know the fact that a Method object wraps a
>> method and a method is not a object.
>>
> Why? Is that even a Ruby thing? It seems so out of place to me that I
would
> assume it is an MRI implementation detail. Do the other Rubies do it that
> way? If so, is it just for efficiency where they are all objects as soon
as
> we need them to be, but keep it lazy and don't bother turning them into
> objects until such time as we know we need it?
Yes. It is a Ruby's concept that a method is not an object.
"A method is a procedure which, when invoked on an object, performs a
set of computations on
10 the object. A method itself is not 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."
No, no. If Ruby did what the diagram shows the program
def m(b)
b = Object.new
p b.object_id
end
a = Object.new
m(a)
p a.object_id
would print the same number because a and b would be pointing to the
same storage area. They aren't.
···
On Fri, Nov 12, 2010 at 12:25 PM, Josh Cheek <josh.cheek@gmail.com> wrote:
On Fri, Nov 12, 2010 at 3:01 AM, Xavier Noria <fxn@hashref.com> wrote:
When the function is invoked the pointer is *copied*, that is, an integer
value is copied and linked to a local variable. The exact same thing
happens if the parameter is int i.
The exact same thing also happens with a reference (at least in C++, I don't
know anything about Perl).
The pointer value is copied into the number variable (pass by value).
You can be certain the caller sees the exact same pointer when
the function call returns.
Please re-read your blog with this in mind, since what you right here in
this quote are calling "pass by value" you, in your blog, call
"pass-by-reference".
In the example, we can see these Method objects don't represent the
method C#meth directly. Then, how do we obtain the object which
represents the method C#meth directly? No, we can't. There is no way.
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.
"A method is a procedure which, when invoked on an object, performs a
set of computations on
10 the object. A method itself is not 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."
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.