How can I pass a reference to a method as an argument, so after finishing the execution of the method the argument gets updated with a new value. ( known as "pass by reference" in other languages ).
puts "val before calling changeValue:= " + val.to_s puts "cad before calling changeValue:=" + cad
changeValue( val, cad )
puts "val before calling changeValue:= " + val.to_s #--- I pretend to print '50' puts "cad before calling changeValue:=" + cad #--- I pretend to print '10'
> How can I pass a reference to a method as an argument, so after > finishing the execution of the method the argument gets updated with a > new value. ( known as "pass by reference" in other languages ).
> puts "val before calling changeValue:= " + val.to_s > puts "cad before calling changeValue:=" + cad
> changeValue( val, cad )
> puts "val before calling changeValue:= " + val.to_s #--- I pretend > to print '50' > puts "cad before calling changeValue:=" + cad #--- I pretend > to print '10'
> Regards > Carlos
Assignment inside method scope is allowed, but creates a different object. What you get back from a method is what the method returns. So you could mimic your desired behavior with...
def f(a, b) return a*10.0/b.to_i, (b.to_i+3).to_s end
x, y = 35, "7" x, y = f( x, y ) #this will make x equal to 50 and y equal to the string "10"
> On 7/25/07, caof2005 <caof2...@gmail.com> wrote: > > Hello Folks
> > My question is the following:
> > How can I pass a reference to a method as an argument, so after > > finishing the execution of the method the argument gets updated with a > > new value. ( known as "pass by reference" in other languages ).
> > puts "val before calling changeValue:= " + val.to_s > > puts "cad before calling changeValue:=" + cad
> > changeValue( val, cad )
> > puts "val before calling changeValue:= " + val.to_s #--- I pretend > > to print '50' > > puts "cad before calling changeValue:=" + cad #--- I pretend > > to print '10'
> > Regards > > Carlos
> Assignment inside method scope is allowed, but creates a different > object. What you get back from a method is what the method returns. > So you could mimic your desired behavior with...
> def f(a, b) > return a*10.0/b.to_i, (b.to_i+3).to_s > end
> x, y = 35, "7" > x, y = f( x, y ) #this will make x equal to 50 and y equal to the string > "10"
> Does that make sense?
> Todd
> What if the method is returning something else already and you don't want
to have to return the changed value? How do you pass in a variable to a method and have the change stick when it exists the method in ruby? Chris
On Thu, 26 Jul 2007, Chris Thiel wrote: > What if the method is returning something else already and you don't want > to have to return the changed value? How do you pass in a variable to a > method and have the change stick when it exists the method in ruby?
You can change an object:
def change_me(str) str.upcase! end
s = "abc" change_me(str) puts s # ABC
But you can't change the bindings. In the example, I've got s and str both containing references to the same string. But the names of the identifiers themselves, s and str, are solely the business of their local scopes, which are different as between the method body and the calling context.
> > What if the method is returning something else already and you don't > want > > to have to return the changed value? How do you pass in a variable to a > > method and have the change stick when it exists the method in ruby?
> You can change an object:
> def change_me(str) > str.upcase! > end
> s = "abc" > change_me(str) > puts s # ABC
> But you can't change the bindings. In the example, I've got s and str > both containing references to the same string. But the names of the > identifiers themselves, s and str, are solely the business of their > local scopes, which are different as between the method body and the > calling context.
def add_one(number) number+=1 end n = 1 add_one(n)
While the method returns 2, the value of n when the method is done is still one.
Or with strings def add_bar(st) st + "bar" end
s = "foo" add_bar(s)
Same thing. The method returns foobar, but the value of s is unchaged. Is there a way to change the values of these variables from within the method and have the values remain changed when the method has exited?
>> What if the method is returning something else already and you don't want >> to have to return the changed value? How do you pass in a variable to a >> method and have the change stick when it exists the method in ruby?
> But you can't change the bindings. In the example, I've got s and str > both containing references to the same string. But the names of the > identifiers themselves, s and str, are solely the business of their > local scopes, which are different as between the method body and the > calling context.
> On 7/25/07, caof2005 <caof2...@gmail.com> wrote:
> > Hello Folks
> > My question is the following:
> > How can I pass a reference to a method as an argument, so after > > finishing the execution of the method the argument gets updated with a > > new value. ( known as "pass by reference" in other languages ).
> > puts "val before calling changeValue:= " + val.to_s > > puts "cad before calling changeValue:=" + cad
> > changeValue( val, cad )
> > puts "val before calling changeValue:= " + val.to_s #--- I pretend > > to print '50' > > puts "cad before calling changeValue:=" + cad #--- I pretend > > to print '10'
> > Regards > > Carlos
> Assignment inside method scope is allowed, but creates a different > object. What you get back from a method is what the method returns. > So you could mimic your desired behavior with...
> def f(a, b) > return a*10.0/b.to_i, (b.to_i+3).to_s > end
> x, y = 35, "7" > x, y = f( x, y ) #this will make x equal to 50 and y equal to the string "10"
> Does that make sense?
> Todd
Todd:
Although it did not change neither of both parameters and I suppose you can't do this in Ruby, at the end you showed me a new technique that can mimic the behavior.
> On 7/25/07, dbl...@wobblini.net <dbl...@wobblini.net> wrote:
> > Hi --
> > On Thu, 26 Jul 2007, Chris Thiel wrote:
> > > What if the method is returning something else already and you don't > > want > > > to have to return the changed value? How do you pass in a variable to > a > > > method and have the change stick when it exists the method in ruby?
> > You can change an object:
> > def change_me(str) > > str.upcase! > > end
> > s = "abc" > > change_me(str) > > puts s # ABC
> > But you can't change the bindings. In the example, I've got s and str > > both containing references to the same string. But the names of the > > identifiers themselves, s and str, are solely the business of their > > local scopes, which are different as between the method body and the > > calling context.
> > I'm talking in a case like this: > def add_one(number) > number+=1 > end > n = 1 > add_one(n)
> While the method returns 2, the value of n when the method is done is > still > one.
> Or with strings > def add_bar(st) > st + "bar" > end
> s = "foo" > add_bar(s)
> Same thing. The method returns foobar, but the value of s is unchaged. > Is there a way to change the values of these variables from within the > method and have the values remain changed when the method has exited?
> Chris
n = add_one(n) would fix your given case. I assume it is more complicated than this?
-- "Hey brother christian with your high and mighty errand, Your actions speak so loud, I can't hear a word you're saying."
Chris Thiel wrote the following on 25.07.2007 20:56 :
> I believe it's adding & in front of the argument in a method in C++ to > get > pass by reference. > void add_one(&num) { > num++ > }
> Is there something that's equivalent in ruby?
Ruby always pass references. The problem is that "number += 1" is expanded as "number = number + 1".
The problem here is that Fixnum#+ doesn't modify the object but generates another one. So in fact it generates what happens is that a new Object is created and then is referenced by number, but not by n. To make it work like you want you would need to only use methods that modify the object itself, which AFAIR don't exist in this context.
Thanks for the response, although I was just wondering that using Strings as a parameters in a method definition is a special case. Let me explain.... I observed that when you use a string as a parameter in a method definition, it can be changed by applying several operations inside the method, for instance you can change it, by adding letters to the string, changing the content to uppercase etc. So I figured out that when you use a string, what really happens inside the method is that you don't create a new object, you just use the reference. In opposition as if you use other kind of parameters in a method definition, let say for example an int variable. If you try to change this int variable inside the method, it simply doesn't work, what happens is that you get a "copy" of the object that you're passing but after the method is finished, that copy disappears and at the end the parameter that you passed was not affected. Am I correct with my conclusions?
> On Thu, 26 Jul 2007, Chris Thiel wrote: > > What if the method is returning something else already and you don't want > > to have to return the changed value? How do you pass in a variable to a > > method and have the change stick when it exists the method in ruby?
> You can change an object:
> def change_me(str) > str.upcase! > end
> s = "abc" > change_me(str) > puts s # ABC
> But you can't change the bindings. In the example, I've got s and str > both containing references to the same string. But the names of the > identifiers themselves, s and str, are solely the business of their > local scopes, which are different as between the method body and the > calling context.
> Chris Thiel wrote the following on 25.07.2007 20:56 : > > I believe it's adding & in front of the argument in a method in C++ to > > get > > pass by reference. > > void add_one(&num) { > > num++ > > }
> > Is there something that's equivalent in ruby?
> Ruby always pass references. The problem is that "number += 1" is > expanded as "number = number + 1".
> The problem here is that Fixnum#+ doesn't modify the object but > generates another one. So in fact it generates what happens is that a > new Object is created and then is referenced by number, but not by n. To > make it work like you want you would need to only use methods that > modify the object itself, which AFAIR don't exist in this context.
> Thanks for the response, although I was just wondering that using > Strings as a parameters in a method definition is a special case. > Let me explain.... > I observed that when you use a string as a parameter in a method > definition, it can be changed by applying several operations inside > the method, for instance you can change it, by adding letters to the > string, changing the content to uppercase etc. > So I figured out that when you use a string, what really happens > inside the method is that you don't create a new object, you just use > the reference. > In opposition as if you use other kind of parameters in a method > definition, let say for example an int variable. > If you try to change this int variable inside the method, it > simply doesn't work, what happens is that you get a "copy" of the > object that you're passing but after the method is finished, that > copy disappears and at the end the parameter that you passed was not > affected. > Am I correct with my conclusions?
> Regards > Carlos
Yes, because a Fixnum object is immutable. Also, like David said, you cannot change bindings. See...
irb> def f x; x = 6; end => nil irb> a = 1 => 1 irb> f a => 6 irb> a => 1
Now look at something that is mutable, like String... irb> a = "hello" => "hello" irb> def g x; x << "bye"; end => nil irb> f a "hellobye" irb> a "hellobye"
But watch this assignment... irb> a = "hello" => "hello" irb> a.__id__ => 68099810 irb> def g x irb> puts x.__id__ irb> x = "bye" #here is an attempt at assignment irb> puts x.__id__ #oops, not correct scope, created new string object with name x irb> end => nil irb> g a 68099810 68052050 => nil irb> a #should be unchanged => "hello"
So yes, mutable objects you can change within method scope, but not reassign. To answer Chris's question about what you should do when you are already returning something, well, you can return more than one thing. You can also send an object as a parameter (Array, Hash, whatever), which of course can be modified within the method.
You're pretty close, just some details as to the whyness:
String are of course instances of the String class. This is simply an array of characters, of which you can modify freely, as you've discovered.
Numbers, on the other hand are special case instances of FixNum, BigNumber, any subclass of Numeric. These have no underlying data representation, they *are* the number they represent. So if you tried to do the same to Fixnums like you can with String, you'd actually be trying to change 1 to equal 2, and you can imagine what kind of havok that would cause.
So with Strings, you have an underlying character array you can play with, but with Numerics you have to change the number your variable is pointing to.
Hopefully I made that understandable, though please correct me if something I said was wrong.
> Thanks for the response, although I was just wondering that using > Strings as a parameters in a method definition is a special case. > Let me explain.... > I observed that when you use a string as a parameter in a method > definition, it can be changed by applying several operations inside > the method, for instance you can change it, by adding letters to the > string, changing the content to uppercase etc. > So I figured out that when you use a string, what really happens > inside the method is that you don't create a new object, you just use > the reference. > In opposition as if you use other kind of parameters in a method > definition, let say for example an int variable. > If you try to change this int variable inside the method, it > simply doesn't work, what happens is that you get a "copy" of the > object that you're passing but after the method is finished, that > copy disappears and at the end the parameter that you passed was not > affected. > Am I correct with my conclusions?
> Regards > Carlos
> On Jul 25, 11:35 am, dbl...@wobblini.net wrote: > > Hi --
> > On Thu, 26 Jul 2007, Chris Thiel wrote: > > > What if the method is returning something else already and you don't > want > > > to have to return the changed value? How do you pass in a variable to > a > > > method and have the change stick when it exists the method in ruby?
> > You can change an object:
> > def change_me(str) > > str.upcase! > > end
> > s = "abc" > > change_me(str) > > puts s # ABC
> > But you can't change the bindings. In the example, I've got s and str > > both containing references to the same string. But the names of the > > identifiers themselves, s and str, are solely the business of their > > local scopes, which are different as between the method body and the > > calling context.
On Thu, 26 Jul 2007, Philip Hallstrom wrote: >> On Thu, 26 Jul 2007, Chris Thiel wrote:
>>> What if the method is returning something else already and you don't want >>> to have to return the changed value? How do you pass in a variable to a >>> method and have the change stick when it exists the method in ruby?
I think it's the clearest explanation so far Jason.
I believe it's a good practice to stop thinking in terms of pointers and start thinking in terms of objects. You don't pass a variable by reference, you pass an object.
With a little time you'll find this approach a lot more comfortable.
Cheers !
On 25/07/07, Jason Roelofs <jameskil...@gmail.com> wrote:
> You're pretty close, just some details as to the whyness:
> String are of course instances of the String class. This is simply an array > of characters, of which you can modify freely, as you've discovered.
> Numbers, on the other hand are special case instances of FixNum, BigNumber, > any subclass of Numeric. These have no underlying data representation, they > *are* the number they represent. So if you tried to do the same to Fixnums > like you can with String, you'd actually be trying to change 1 to equal 2, > and you can imagine what kind of havok that would cause.
> So with Strings, you have an underlying character array you can play with, > but with Numerics you have to change the number your variable is pointing > to.
> Hopefully I made that understandable, though please correct me if something > I said was wrong.
> Jason
> On 7/25/07, caof2005 <caof2...@gmail.com> wrote:
> > Thanks for the response, although I was just wondering that using > > Strings as a parameters in a method definition is a special case. > > Let me explain.... > > I observed that when you use a string as a parameter in a method > > definition, it can be changed by applying several operations inside > > the method, for instance you can change it, by adding letters to the > > string, changing the content to uppercase etc. > > So I figured out that when you use a string, what really happens > > inside the method is that you don't create a new object, you just use > > the reference. > > In opposition as if you use other kind of parameters in a method > > definition, let say for example an int variable. > > If you try to change this int variable inside the method, it > > simply doesn't work, what happens is that you get a "copy" of the > > object that you're passing but after the method is finished, that > > copy disappears and at the end the parameter that you passed was not > > affected. > > Am I correct with my conclusions?
> > Regards > > Carlos
> > On Jul 25, 11:35 am, dbl...@wobblini.net wrote: > > > Hi --
> > > On Thu, 26 Jul 2007, Chris Thiel wrote: > > > > What if the method is returning something else already and you don't > > want > > > > to have to return the changed value? How do you pass in a variable to > > a > > > > method and have the change stick when it exists the method in ruby?
> > > s = "abc" > > > change_me(str) > > > puts s # ABC
> > > But you can't change the bindings. In the example, I've got s and str > > > both containing references to the same string. But the names of the > > > identifiers themselves, s and str, are solely the business of their > > > local scopes, which are different as between the method body and the > > > calling context.
On Thu, 26 Jul 2007, Okushi wrote: > I think it's the clearest explanation so far Jason.
> I believe it's a good practice to stop thinking in terms of pointers > and start thinking in terms of objects. > You don't pass a variable by reference, you pass an object.
Or... you pass a reference by variable :-) I think it's useful to know that you're passing references around:
a = "abc" b = a b << "def" a # "abcdef"
vs. immediate values (symbols, integers), though of course it does all indeed converge on objects.
On Jul 25, 2007, at 4:43 PM, dbl...@wobblini.net wrote:
> I think it's useful to > know that you're passing references around:
> a = "abc" > b = a > b << "def" > a # "abcdef"
> vs. immediate values (symbols, integers), though of course it does all > indeed converge on objects.
I go even farther and simply think of symbols and integers to also be references. Within that context, the literal 1 is simply a textual representation of a reference to the object that behaves like the integer 1. The fact that the Ruby interpreter doesn't actually allocate memory for the object itself is just an implementation detail.
On Tue, 7 Aug 2007, Gary Wright wrote: > On Jul 25, 2007, at 4:43 PM, dbl...@wobblini.net wrote: >> I think it's useful to >> know that you're passing references around:
>> a = "abc" >> b = a >> b << "def" >> a # "abcdef"
>> vs. immediate values (symbols, integers), though of course it does all >> indeed converge on objects.
> I go even farther and simply think of symbols and integers to also be > references. Within that context, the literal 1 is simply a textual > representation of a reference to the object that behaves like the integer 1. > The fact that the Ruby interpreter doesn't actually allocate memory for > the object itself is just an implementation detail.
I'd agree about the literal 1 in comparison with other literals:
1 # textual representation of that object "hi" # textual representation of that object [1,2,3] # etc.
but if you do this:
a = 1 b = "hi"
now a (as I understand it) is actually bound to the integer 1, while b is bound to a reference to the object. (I can't say "A reference to 'hi'" since that 'hi' would be a different one.... :-)
The reason I think it can be good to keep that difference in view is that it has some explanatory power -- especially when the question arises about why there's no a++ (which, because a *is* 1, would be like 1++).
> > On Jul 25, 2007, at 4:43 PM, dbl...@wobblini.net wrote: > >> I think it's useful to > >> know that you're passing references around:
> >> a = "abc" > >> b = a > >> b << "def" > >> a # "abcdef"
> >> vs. immediate values (symbols, integers), though of course it does all > >> indeed converge on objects.
> > I go even farther and simply think of symbols and integers to also be > > references. Within that context, the literal 1 is simply a textual > > representation of a reference to the object that behaves like the > integer 1. > > The fact that the Ruby interpreter doesn't actually allocate memory for > > the object itself is just an implementation detail.
> I'd agree about the literal 1 in comparison with other literals:
> 1 # textual representation of that object > "hi" # textual representation of that object > [1,2,3] # etc.
> but if you do this:
> a = 1 > b = "hi"
> now a (as I understand it) is actually bound to the integer 1, while b > is bound to a reference to the object. (I can't say "A reference to > 'hi'" since that 'hi' would be a different one.... :-)
> The reason I think it can be good to keep that difference in view is > that it has some explanatory power -- especially when the question > arises about why there's no a++ (which, because a *is* 1, would be > like 1++).
If 1 and "hi" were methods, they might look like this:
val = 1 define_method(:one) { val }
define_method(:hi) { val = String.new; val[0] = ?h; val[1] = ?i; val }
a = one() b = hi() c = hi() d = one()
this seemed to illustrate it better in my head. Seeing it typed out, it doesn't look so insightful. I guess what I'm trying to say is. don't think of literals as ways of referring to objects, think of them as method calls that return objects. Or something like that.
> this seemed to illustrate it better in my head. Seeing it typed > out, it > doesn't look so insightful. I guess what I'm trying to say is. > don't think > of literals as ways of referring to objects, think of them as > method calls > that return objects. Or something like that.
It is confusing to me to even think about methods returning objects unless you are using that as a very specific shorthand for saying that methods return *references* to objects. That is the unifying idea that helped me understand how Ruby manipulates data--it is all references and not the objects themselves. The objects themselves are almost completely hidden from the programmer (excluding C extensions) in Ruby. Everything is a reference to an object. At least that is the way I have come to understand things but it means that you have to ditch the idea that Fixnum's and Symbols (and true, false, nil) are somehow special cases. In my mind they are not. The literals :blue, 42, true, false, nil are all references to particular objects and assignment is the process of binding a reference to a variable.
Of course I'm not talking about the underlying *implementation* that Ruby uses to make this all efficient. I'm talking about the abstract semantics of Ruby's object model.
On Aug 6, 2007, at 3:28 PM, dbl...@rubypal.com wrote:
> I'd agree about the literal 1 in comparison with other literals:
> 1 # textual representation of that object > "hi" # textual representation of that object > [1,2,3] # etc.
In the way I think about things those examples are not the same.
An integer literal is a representation of a constant reference to a particular object. It doesn't matter how many times the literal appears in the text, it will always refer to a particular object, in this case the Fixnum instance that behaves like the integer 1. There is no object creation involved when an expression like 1 or 42 is encountered by Ruby unlike your second two examples.
"hi" is special syntax for constructing a brand new instance of String and [1,2,3] is a special syntax for constructing a brand new instance of Array.
(1..10).map { 1 } # array has 10 identical references (1..10).map { "hi" } # array has 10 different references
> but if you do this:
> a = 1 > b = "hi"
> now a (as I understand it) is actually bound to the integer 1, while b > is bound to a reference to the object. (I can't say "A reference to > 'hi'" since that 'hi' would be a different one.... :-)
The way I think about this is that
a = 1
binds a to the reference for the Fixnum instance 1. And in
b = "hi"
the right hand side causes a new instance of String to be instantiated and the reference to that new instance is bound to b.
In both cases, the rhs evaluates to a reference, which is bound to a variable. I like that symmetry.
> On Aug 6, 2007, at 8:16 PM, Logan Capaldo wrote:
>> this seemed to illustrate it better in my head. Seeing it typed out, it >> doesn't look so insightful. I guess what I'm trying to say is. don't think >> of literals as ways of referring to objects, think of them as method calls >> that return objects. Or something like that.
> It is confusing to me to even think about methods returning objects unless > you are using that as a very specific shorthand for saying that methods > return *references* to objects. That is the unifying idea that helped me > understand how Ruby manipulates data--it is all references and not the > objects themselves. The objects themselves are almost completely hidden > from the programmer (excluding C extensions) in Ruby. Everything is a > reference to an object. At least that is the way I have come to understand > things but it means that you have to ditch the idea that Fixnum's and > Symbols (and true, false, nil) are somehow special cases. In my mind they > are not. The literals :blue, 42, true, false, nil are all references to > particular objects and assignment is the process of binding a reference to > a variable.
You're using the term "reference" in two different ways, though: first, as a synonym for a literal constructor (the actual "ink on the page", so to speak), and second as the thing bound to an object. But consider something like:
a = "blue".to_sym
or
x = 10 + 10
The literals :blue and 20 never occur, but a and x are in exactly the same state they'd be in if I'd done:
a = :blue x = 20
So my variables must be bound to something other than a reference, if "reference" means the those literals.
I guess I'd say that:
:blue "blue".to_sym 10 + 10 20
etc. are expressions (rather than references), and that every expression evaluates to an object. Then there's the question of what happens with assignment. I'm not sure how "canonical" the notion of the universal reference is (not just as a matter of implementation) -- but it probably doesn't matter too much either way as long as (im)mutability and uniqueness, which are really object properties, are clear. My only concern is cases where the fact that something is an immediate value might explain some behavior that might otherwise seem unclear or pointless (like the ++ operator case).
On Aug 7, 2007, at 5:18 PM, dbl...@rubypal.com wrote:
> You're using the term "reference" in two different ways, though: > first, as a synonym for a literal constructor (the actual "ink on the > page", so to speak), and second as the thing bound to an object.
Perhaps that was just sloppiness on my part. I think of a 'reference' as the bit pattern that some particular Ruby implementation uses to identify an object. The point I was trying to communicate is that I view literals such as 1 42 true false :blue
as syntactical constructs that map directly to the particular bit pattern that the Ruby interpreter uses to reference the associated objects. I think of them as 'literal references' as opposed to 'literal objects' or 'literal values'. I'm not claiming that I'm using any sort of accepted terminology. I'm just trying to communicate how I think about these things.
> The literals :blue and 20 never occur, but a and x are in exactly the > same state they'd be in if I'd done:
> a = :blue > x = 20
> So my variables must be bound to something other than a reference, if > "reference" means the those literals.
Well, I guess my point is that the Ruby interpreter, as part of its parsing job, must convert :blue as found in the source code to whatever internal representation of a symbol reference it is going to use and similarly for 20 (and nil, false, true).
The fact that the conversion can be done at *parse* time rather than later on at execution time point out how :blue and 20 are distinctly different than 'hello' and [1,2,4], which can only be converted to object references at runtime since it involves instantiating new objects every time the code is executed.
> I guess I'd say that:
> :blue > "blue".to_sym > 10 + 10 > 20
> etc. are expressions (rather than references), and that every > expression evaluates to an object.
And I would say that they are all expressions that evaluate to object references. Are you are saying that those particular expressions are special because the 'standard' behavior is to return an object instance that happens to be encoded right in the value of the reference vs. some indirection into the heap? That is an implementation detail. Surely I could write a version of the Ruby interpreter that actually allocated an object from the heap for Fixnums. It would be slow and it would have to ensure that there was only one 1 and one 2 and so on but that implementation could still implement the same language semantics.
> Then there's the question of what > happens with assignment. I'm not sure how "canonical" the notion of > the universal reference is (not just as a matter of implementation) -- > but it probably doesn't matter too much either way as long as > (im)mutability and uniqueness, which are really object properties, are > clear.
I agree with the uniqueness point but I'm not so sure about immutability. Fixnums can have instance variables...
> My only concern is cases where the fact that something is an > immediate value might explain some behavior that might otherwise seem > unclear or pointless (like the ++ operator case).
But there is always all sorts of hand waving about assignment semantics that include different rules for 'regular' objects and for 'value' objects (nil, true, false, Fixnum, Symbol). If you view 1 as a value (i.e. an object) then you have to have those different rules to explain how everything works. If you view 1 as a reference to an object (even if the object is a virtual object whose creation is 'optimized' away via some creative bit-twiddling) then you don't have to have all those different rules. I like that.
>> etc. are expressions (rather than references), and that every >> expression evaluates to an object.
> And I would say that they are all expressions that evaluate to object > references. Are you are saying that those particular expressions are > special because the 'standard' behavior is to return an object instance > that happens to be encoded right in the value of the reference > vs. some indirection into the heap?
No, I really meant to lump all expressions together, pretty much. I probably should have thrown in some non-symbol/integer ones.
> That is an implementation detail. > Surely I could write a version of the Ruby interpreter that actually > allocated an object from the heap for Fixnums. It would be slow and > it would have to ensure that there was only one 1 and one 2 and so on > but that implementation could still implement the same language semantics.
>> Then there's the question of what >> happens with assignment. I'm not sure how "canonical" the notion of >> the universal reference is (not just as a matter of implementation) -- >> but it probably doesn't matter too much either way as long as >> (im)mutability and uniqueness, which are really object properties, are >> clear.
> I agree with the uniqueness point but I'm not so sure about immutability. > Fixnums can have instance variables...
I'm not sure what the right terminology is for the thing that you can't change in Fixnums, Symbols, etc. Basically I mean the fact that you can't turn 1 into 2, even though you can embellish 1 with state.
>> My only concern is cases where the fact that something is an >> immediate value might explain some behavior that might otherwise seem >> unclear or pointless (like the ++ operator case).
> But there is always all sorts of hand waving about assignment semantics > that include different rules for 'regular' objects and for 'value' > objects (nil, true, false, Fixnum, Symbol). If you view 1 as a value > (i.e. an object) then you have to have those different rules to explain > how everything works. If you view 1 as a reference to an object (even > if the object is a virtual object whose creation is 'optimized' away > via some creative bit-twiddling) then you don't have to have all those > different rules. I like that.
I'm thinking more about variables than literals, though, because that's where the questions arise. It's easy to see that 1++ is meaningless; but it's harder, I've found at least, to explain why:
x = 1 x++
wouldn't make sense, without recourse to explaining the immediate presence of 1 in x.
I'm certainly in the market for continuing to think this through, as I'm always interested in ways to explain what Ruby is doing in the most expressive way possible. It's only when I think that people will get *more* confused, rather than less, without it, that I trot out the immediate value stuff. It's definitely not in the interest of pushing implementation details into view; it's more a matter of accounting for the semantics of the language and the behavior of its methods (things like ++ and why one can't append to symbols).