Question - Passing parameters by reference

C

caof2005

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

example:
.....
def changeValue( val, cad )
temp = 0;
val = (val * 10) / cad.to_i
temp = cad.to_i + 3.to_i
cad = temp.to_s
end
.....
.....
val = 35;
cad = "7"

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
 
T

Todd Benson

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

example:
....
def changeValue( val, cad )
temp = 0;
val = (val * 10) / cad.to_i
temp = cad.to_i + 3.to_i
cad = temp.to_s
end
....
....
val = 35;
cad = "7"

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
 
D

dblack

Hi --

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.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
C

caof2005

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.

Thanks so much for this tip!!!

Carlos
 
L

Lionel Bouton

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.

Lionel.
 
C

caof2005

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
 
T

Todd Benson

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.

cheers,
Todd
 
O

Okushi

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 !
 
D

dblack

Hi --

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.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
G

Gary Wright

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.

Gary Wright
 
D

dblack

Hi --

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


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
G

Gary Wright

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.

Gary Wright
 
G

Gary Wright

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.

Gary Wright
 
D

dblack

Hi --

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


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
G

Gary Wright

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

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

dblack

Hi --

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.


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


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
G

Gary Wright

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.

Take a look at this message from Matz:
<http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/20236>.

I have to think about this a bit more, but it isn't clear to me
why the concept of immediate values needs to be introduced in order
to explain the problems with x++ in Ruby.

It seems to me that the idea of immediate values is not something
inherent in Ruby's semantics but instead is baggage that arrives
with programmers (myself included) coming from other languages.
We try to find a place for it in Ruby when it isn't really needed.
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).

Do those examples really require the introduction of immediate values?

Once you understand that there is a one-to-one mapping between Fixnum
instances and a subset of the integers it is clear why you can't
'increment' a Fixnum instance. It is a nonsensical concept yet the
concept of 'successor' is well-defined.

Similarly once you understand that there is a one-to-one mapping between
Symbol instances and their 'label' it is clear why you can't 'append'
something to the label and still have the same symbol. The identity
of a Symbol instance is inherently tied to its label and it is that
isomorphism that makes Symbols useful.

I'm not sure how much more juice we can squeeze out of this orange but
looking back at this thread it seems that the OP was looking for a
way to change the 'value' of a Fixnum method argument in the same
way that the 'value' of a String method argument can be changed.
Cue the immediate value discussion.

Instead of using the immediate value abstraction though, the
situation can be explained by correcting the erroneous assumption
that fixnum objects are containers for an integer value that can
be changed. There is an extra level of indirection in the string
case that simply doesn't exist in the fixnum case.

Gary Wright
 
D

dblack

Hi --

Take a look at this message from Matz:
<http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/20236>.

I have to think about this a bit more, but it isn't clear to me
why the concept of immediate values needs to be introduced in order
to explain the problems with x++ in Ruby.

It seems to me that the idea of immediate values is not something
inherent in Ruby's semantics but instead is baggage that arrives
with programmers (myself included) coming from other languages.
We try to find a place for it in Ruby when it isn't really needed.

I don't know -- in my case, I just always remember reading and
learning that a = 1 resulted in a having the immediate value of 1
(specifically in Ruby, I mean). I have no instinct or incentive to
introduce or find a place for the concept if it isn't there already.
My understanding, which could be wrong, is that that's how things were
actually happening. And remember that the whole concept of an
"implementation detail" is relatively new in Ruby, since it's only
recently that we've started dealing concretely with multiple
implementations and the whole set of issues surrounding what is and is
not a Ruby implementation.
Do those examples really require the introduction of immediate values?

Again, I can't speak to the introduction point directly, because my
impression is that the immediate value thing is already there. But as
to the explanatory value -- I've always reached for the immediate
value, unique, immutable explanation because I thought it was accurate
and it helped people understand what was happening and how to use the
objects. I've therefore never seen the need to look further. (Call
it "Black's Razor", or something :)

I don't know whether it's necessary or not, though. It's certainly
not a magic bullet, especially in the case of symbols.
[... various interesting ideas for other ways of explaining thigns
...]

Instead of using the immediate value abstraction though, the
situation can be explained by correcting the erroneous assumption
that fixnum objects are containers for an integer value that can
be changed. There is an extra level of indirection in the string
case that simply doesn't exist in the fixnum case.

It's interesting -- I think it's always about that extra level of
indirection, and perhaps just a matter of where one assigns it a place
in the diagram, so to speak.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 

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

No members online now.

Forum statistics

Threads
474,266
Messages
2,571,318
Members
47,998
Latest member
GretaCjy4

Latest Threads

Top