pass by reference?

T

Thomas Hafner

Phrogz said:
On Jan 26, 4:32 pm, Vincent Fourmond <[email protected]>
How do you know if those are passed by reference or by value?

def oi(obj)
obj.object_id
end
x = "yeah" # or set it to anything else
oi(x) == x.object_id # => true

Regards
Thomas
 
A

Austin Ziegler

You don't actually need to do anything: everything in ruby is passed
by reference, (excepted integers, symbols, nil, false and true - am I
missing one ?)

Those are still passed by reference. It just so happens that they are
unique and immutable in the system, so it looks a lot like
pass-by-value.

-austin
 
X

Xavier Noria

Those are still passed by reference. It just so happens that they are
unique and immutable in the system, so it looks a lot like
pass-by-value.

I think the problem in these discussions is that "reference" in the
programming language jargon is not the same word as in "pass-by-
reference". This discussion is common in Java forums as well. Java is
pass-by-value.

In C++ since the copy constructor is involved, I found people in
freenode#c++ consider &-arguments to be pass-by-reference because
they can modify the objects in the caller, albeit the assigment test
discussed in the thread does not work, that'd be

def m(b)
b = 7
end

a = 3
m(a)
# a expected to be 7 in pass-by-reference

-- fxn
 
T

Thomas Hafner

Xavier Noria said:
In C++ since the copy constructor is involved, I found people in
freenode#c++ consider &-arguments to be pass-by-reference because
they can modify the objects in the caller, albeit the assigment test
discussed in the thread does not work, that'd be

def m(b)
b = 7
end

a = 3
m(a)
# a expected to be 7 in pass-by-reference

That's another story. With the code above you rather reset b to a new
object instead of modifying the passed object. Look here:

def m(b)
b.shift
b.unshift(7)
end
a = [3]
m(a)
=> [7]

Would that be the same with pass-by-value? No, I don't think so.

Regards
Thomas
 
X

Xavier Noria

That's another story. With the code above you rather reset b to a new
object instead of modifying the passed object. Look here:

def m(b)
b.shift
b.unshift(7)
end
a = [3]
m(a)
=> [7]

Would that be the same with pass-by-value? No, I don't think so.

Yes, that's the usual point in the discussion. Being able to change
the internal state of mutable objects is not a test for pass-by-
reference. Java is pass-by-value for instance (according to the JLS)
and that test passes.

Problem with the assignment-seen-in-the-caller test is what dblack
pointed out, it mixes assigment semantics.

In Perl, which is pass by reference, you can do this for example:

$ perl -wle '$x = 0; sub { ++$_[0] }->($x); print $x'
1

-- fxn
 
A

Austin Ziegler

The simplest way to remember this is that variables in Ruby aren't
chunks of memory. When C++ programmers say that they're passing
something by reference, they are simply doing a (slightly) safer
operation than passing a pointer around. They are *still* referencing
the memory block, but it's type checked.

In Ruby, inasmuch as variables contain anything, they contain a
reference. This applies even to immediate values such as nil, true,
false, integers, and symbols. It just so happens that, at least for
integers, the reference (the object ID, if you will) is the same as
the value, shifted left once -- at least in matzruby. The others are
all fixed object IDs.

Making a distinction between the passing semantics of immediate values
is a mistake; it invites people to peer too deeply under the hood of
Ruby. Better to clarify that integers are immediate immutable values
and indicate that all variables are references and the references are
passed -- by value -- to methods.

Scope also enters into this, but that's been discussed clearly.

-austin
 
D

dblack

Hi --

Xavier Noria said:
In C++ since the copy constructor is involved, I found people in
freenode#c++ consider &-arguments to be pass-by-reference because
they can modify the objects in the caller, albeit the assigment test
discussed in the thread does not work, that'd be

def m(b)
b = 7
end

a = 3
m(a)
# a expected to be 7 in pass-by-reference

That's another story. With the code above you rather reset b to a new
object instead of modifying the passed object. Look here:

def m(b)
b.shift
b.unshift(7)
end
a = [3]
m(a)
=> [7]

Would that be the same with pass-by-value? No, I don't think so.

It depends what value you're passing. If the value is an array, and
it gets copied into b, then it wouldn't work that way; but what's
happening is that a *reference* to an array is getting passed by
value. That value (which is a reference to an array) is assigned to
the variable a in the caller's scope, and also to the variable b
inside the method.


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
T

Thomas Hafner

Austin Ziegler said:
The simplest way to remember this is that variables in Ruby aren't
chunks of memory.

Or: they are a chunk of memory, but the only kind of value they can
contain is a reference to an object. A variable is not such an object,
i.e. there are no references to variables.

Ruby
~~~~

Var. obj.-id object
+---+ +---+
a --->| | | |
| |--->| |
b --->| | | |
+---+ | |
| |
| |
| |
| |
+---+

If one passes a value, always an object id will be passed.

If one just uses variable ``a'', it will always go through the
automatial indirection of the object id. If ``a'' and ``b'' go through
the same indirection (using the same object id), then state can be
manipulated mutually.


C
~

Var. memory
+---+
a --->| |
| |
b --->| |
| |
| |
| |
| |
| |
+---+

If one passes a value, the memory will be copied. Then state can no
longer be manipulated.

Regards
Thomas
 
F

fxn

Hi --

On 27.01.2007 01:43, (e-mail address removed) wrote:
Hi --

On Sat, 27 Jan 2007, Martin C. Martin wrote:

Phrogz wrote:
If you pass an immutable type by reference, does it make a sound?
Er, I mean...
If you passed an immutable type by reference, how would you know
that
it wasn't passed by value?

Is there any way for the function you're calling to modify the value
of
the variable in the caller? Pass by reference can do that.

You can modify the object to which the variable refers:

def change_me(obj)
obj << "hi"
end

arr = [1,2,3]
change_me(arr)
p arr # [1, 2, 3, "hi"]

In this example, arr contains a reference to an array. In change_me,
obj contains another copy of the same reference, so you can use it to
manipulate and change the original array.

I still wouldn't call this pass by reference (see my earlier post in
this thread).

Absolutely right: Ruby uses pass by value - with references.

irb(main):004:0> def foo(x) x = 10 end
=> nil
irb(main):005:0> def bar; x = 20; foo(x); x end
=> nil
irb(main):006:0> bar
=> 20
irb(main):007:0>

I'm not sure that demonstrates the "values that are references" thing,
though. You're reassigning to x in foo, which creates a new local x;
but I think that's just part of the assignment semantics. Or are you
assuming that if pass by reference were involved, then assignment
would work differently?

*** NEWBIE WARNING ***

I'm entering this thread as it gives me a chance to test my own
understanding.
My apologies if I've missed the mark!

I agree the example doesn't show pass by reference v pass by value. I
think it
shows more about scope.

However, I think what he was trying to show was that if what was being
passed
was the address of the variable in the callers environment, then changes
to
what that variable pointed at would be seen in the callers environment as
well.

i.e.

a = Array.new could look like this

-------
| a | ----------
| ----------->|Array Obj|
| | ----------
------- Addr = 1000
Addr = 0

Here 'a' holds the value 1000, the address of the array object. This value
(1000) is stored in location 0. 'a' points to the storage location. In C
it
would be called a pointer, in ruby, its just a variable because yo don't
have
anything else. some would say 'a' is bound to the address 1000, which is
the
start location of an array object.

Some of this confusion about passed by value and passed by reference is
due to
C and how it worked. In C, by default, things are passed by value

Ruby takes a different approach to C. In ruby, all variables are really
references to objects stored somewhwere else. The overheads associated
with
arguement passing are the same regardless of the size or type of object
the
variable references - its just an address. This means the traditional C
pass by
reference

I think those statements were informal, but just for the archives C only
has pass-by-value.

Sometimes people think that, say, modifying an integer through a pointer
argument shows pass-by-reference. But it doesn't, the argument is the
pointer there, and is passed by value.

-- fxn
 
F

fxn

Xavier said:
Could you point me to the exact locus?

Sure, that's section 8.4.1 in the current edition[*]:

"When the method or constructor is invoked (§15.12), the values of the
actual argument expressions initialize newly created parameter variables,
each of the declared Type, before execution of the body of the method or
constructor. The Identifier that appears in the DeclaratorId may be used
as a simple name in the body of the method or constructor to refer to the
formal parameter."

-- fxn

[*] http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.1
 
J

Julian Tarkhanov

Is there a way to pass variables by reference into function.

I have large string to pass and the pass by value seems to be
eating up too much memory.

Strings are mutable objects and should be treated as such :)

def append_sour_word(strbuf)
strbuf << " ...uck!"
end

text = "Good l"

append_sour_word(text) #=> "Good luck" is returned AND is contained
in text now
text #=> "Good luck"

def assign_concatenated(strbuf)
strbuf = strbuf + " ...uck!"
end

assign_concatenated(text) #=> "This is some new text" is returned but
you lost the reference inside the function scope so the actual
_value_ stays the same
text #=> still "Good luck", because you assigned another reference to
your variable

def replace_content(strbuf)
strbuf.replace(strbuf + " ...uck!")
end

replace_content(text) "Good l..uck!..uck!", but now with a desired
side effect

text #=> "Good l..uck!..uck!", now you replaced the object with
another one

Basically, to avoid confusion - if you eating up RAM avoid object
_duplication_, because that's what eats it up. But it's perfectly
possible to
massage objects in place without having to ask them for their "actual
value".
 
G

Grant Hutchins

def modifying(a_param)
a_param = "hi"
end

def modifying2(a_param=a_value)
a_param = "hi"
end

In these two methods, the = sign is an assignment, which changes the
memory location of the lvalue to point to the object of the rvalue.
def modifying3(a_param)
a_param[0..-1]= "hi"
end

This is actually a method call. It could also be written a_param.
[]=(0..-1, "hi") . So the difference is that in this example you are
actually calling a method on the object that a_param points to. This
is due to the syntactic sugar Ruby gives to the method named []= which
in this case is defined on String. See http://www.ruby-doc.org/docs/
ruby-doc-bundle/Manual/man-1.4/syntax.html#assign

So in all three we are passing by value as you define it.
 
A

Austin Ziegler

Or: they are a chunk of memory, but the only kind of value they can
contain is a reference to an object. A variable is not such an object,
i.e. there are no references to variables.

It's better not to consider variables in Ruby as anything but a label
and as such *not* a chunk of memory. Chunks of memory suggest object
status or possibilities; this is not part of Ruby.

Your graphs are pretty close to correct. I have to finish some
articles talking about variables in Ruby and post them at some point.

-austin
 
A

Austin Ziegler

So, how successfully has that been at muddying the water? Everyone now nicely
confused?

Your description seems to be okay, but forget "address" when dealing
with Ruby variables. It's not an appropriate concept and only muddies
the waters unnecessarily.

-austin
 
A

Austin Ziegler

In these two methods, the =3D sign is an assignment, which changes the
memory location of the lvalue to point to the object of the rvalue.

When talking about Ruby variables, it is ALWAYS incorrect to refer to
a "memory location." It's not a concept that has any useful meaning in
Ruby. Ever.

-austin
--=20
Austin Ziegler * (e-mail address removed) * http://www.halostatue.ca/
* (e-mail address removed) * http://www.halostatue.ca/feed/
* (e-mail address removed)
 

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,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top