Pass by reference or pass by value


#1

hi,
I couldnt figure out if ruby works with pass by value or pass by reference… Whats the catch? is it simple types, complex types?

pass by value example:

def hop(onur)
onur=onur+1
end

ahmet=5
hop(ahmet)

ahmet
=> 5

pass by reference example:

def lala(node)
node.body=“hoppa”
end

n= Node.new
lala(n)
n.body
=> “hoppa”


#2

On 6/12/2005, at 9:56 AM, Onur T. wrote:

I couldnt figure out if ruby works with pass by value or pass by reference… Whats the catch? is it simple types, complex types?

Ruby only has objects, so pass by ‘value’ is nonsensical, there are
only references. Consequently Ruby has no ‘simple’ types.

However, watch for methods that return new object. int + int returns
a new int, it doesn’t modify the value of the old int. That’s the
difference between string.gsub and string.gsub! - the latter modifies
the object, the former returns a new string. This pattern is followed
in many of the Ruby libraries.


Phillip H.
removed_email_address@domain.invalid


#3

Well, actually Ruby is ‘pass by value’ language.

Here is the proof:

irb(main):001:0> def swap(a,b)
irb(main):002:1> a,b = b,a
irb(main):003:1> end
=> nil
irb(main):004:0> a,b = 1,2
=> [1, 2]
irb(main):005:0> swap a,b
=> [2, 1]
irb(main):006:0> puts a,b
1
2
=> nil

If Ruby were ‘pass by reference’, a and b variables would be 2 and 1
respectively.

Cheers,
Kent.


#4

I got it… thanks a lot.


#5

On Tue, 6 Dec 2005, Kent S. wrote:

irb(main):005:0> swap a,b
=> [2, 1]
irb(main):006:0> puts a,b
1
2
=> nil

If Ruby were ‘pass by reference’, a and b variables would be 2 and 1
respectively.

it’s more complicated than that.

harp:~ > cat a.rb
a = []
def add list, value
list << value
end

add a, 42

p a

harp:~ > ruby a.rb
[42]

the reason your swap method doesn’t work is that cow (copy on write) and
scoping are confusing the issue.

first, ruby uses copy on write so:

harp:~ > cat a.rb
a = []
b = a

a << 42
p b
p a

b = ‘forty-two’
p b
p a

harp:~ > ruby a.rb
[42]
[42]
“forty-two”
[42]

notice that at first b is ‘pointing’ to a. but after it’s assigned to
it has a
different value.

so your swap method does this

def swap(a,b)

here a and b both refer to the variable passed in

 a,b = b,a

on the rhs b and a are the passed in values. on the lhs you introduce

two #

local variables which, due to copy on write, obtain new values while

preserving

the orignial a and b

end

nevertheless, ruby is strictly pass by reference. for instance, this
swap
method will work fine:

 harp:~ > cat a.rb
 require "yaml"

 def swap a, b
   da, db = a.dup, b.dup
   a.replace db
   b.replace da
   return [ b, a ]
 end

 a, b = "foo", "bar"
 swap a, b

 y "a" => a, "b" => b


 harp:~ > ruby a.rb
 ---
 a: bar
 b: foo

regards.

-a

===============================================================================
| ara [dot] t [dot] howard [at] noaa [dot] gov
| all happiness comes from the desire for others to be happy. all misery
| comes from the desire for oneself to be happy.
| – bodhicaryavatara


#6

just out of curiosity; is there a way that I can increase the value of
an
integer without introducinw Integer objects into the scope?


#7

On 12/6/05, Kent S. removed_email_address@domain.invalid wrote:

Well, actually Ruby is ‘pass by value’ language.

Here is the proof:

If Ruby were ‘pass by reference’, a and b variables would be 2 and 1
respectively.

Yes and no. When you pass an argument into a method, you are passing a
variable that points to a reference. In a way, it’s a combination of
pass by value and pass by reference. What I mean is, you pass the
value of the variable in to the method, however the value of the
variable is always a reference to an object.

The difference between:

def my_method( a )
a.gsub!( /foo/, ‘ruby’ )
end

str = ‘foo is awesome’
my_method( str ) #=> ‘ruby is awesome’
str #=> ‘ruby is awesome’

and:

def your_method( a )
a = a.gsub( /foo/, ‘ruby’ )
end

str = ‘foo is awesome’
my_method( str ) #=> ‘ruby is awesome’
str #=> ‘foo is awesome’

is that in #my_method, you are calling #gsub! which changes the object
(a) in place. Since the ‘str’ variable (outside the method scope) and
the ‘a’ variable (inside the method scope) both have a “value” that is
a reference to the same object, the change to that object is reflected
in the ‘str’ variable after the method is called. In #your_method, you
call #gsub which does not modify the original object. Instead it
creates a new instance of String that contains the modifications. When
you assign that object to the ‘a’ variable, you are changing the value
of ‘a’ to be a reference to that new String instance. However, the
value of ‘str’ still contains a reference to the original (unmodified)
string object.


Regards,
John W.
http://johnwilger.com


Alice came to a fork in the road. “Which road do I take?” she asked.
“Where do you want to go?” responded the Cheshire cat.
“I don’t know,” Alice answered.
“Then,” said the cat, “it doesn’t matter.”

  • Lewis Carrol, Alice in Wonderland

#8

On 6/12/2005, at 8:34 PM, Onur T. wrote:

just out of curiosity; is there a way that I can increase the value
of an integer without introducinw Integer objects into the scope?

No, you can’t modify an integer object. This is a speed optimisation
so that a full object isn’t created to run an integer.


Phillip H.
removed_email_address@domain.invalid


#9

On 12/6/05, Phillip H. removed_email_address@domain.invalid wrote:


Phillip H.
removed_email_address@domain.invalid


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

[Onur] It may be educational to be checking Object#id in the above
examples
(add a bunch of puts to the code).

[John] Try these defs on for size :
With pointers, we can pass the values ‘by reference.’ Passing by
reference
means that we’ll pass the addresses of the variables instead of the
values. pass-by-value vs.
pass-by-referencehttp://www.cs.princeton.edu/~lworthin/126/precepts/pass_val_ref.html


#10

On 12/6/05, Peter F. removed_email_address@domain.invalid wrote:

removed_email_address@domain.invalid

Joyeux Noël

Peter F.

[Onur] BTW: Object#id exists for every type in Ruby… since everything
is
an “object” and is inherited from Object!


#11

does that mean integer is not a full object?


#12

On Tue, 6 Dec 2005, Onur T. wrote:

does that mean integer is not a full object?

yes. all variables in ruby are essentially pointers that contain the
address
of their object. integers are very speical - the whole object is
the
pointer - it can be done because ruby uses 31 bits for variables and a
test of
a single bit lets it know if the variable is an integer or a pointer to
object.

-a


#13

On Tue, 6 Dec 2005, Peter F. wrote:

[Onur] It may be educational to be checking Object#id in the above examples
(add a bunch of puts to the code).

[John] Try these defs on for size :
With pointers, we can pass the values ‘by reference.’ Passing by reference
means that we’ll pass the addresses of the variables instead of the
values. pass-by-value vs.
pass-by-referencehttp://www.cs.princeton.edu/~lworthin/126/precepts/pass_val_ref.html

does this function pass by value or reference?

void foo (void *object);

well - both in a sense. it takes a reference and that reference is
passed by
value. this is how ruby works because all variables are already
pointers - in
one sense they are passed by value since a copy of the address is placed
on
the stack and in another sense they are passed by reference since only
object
addresses, and never there values, are placed on the stack. in short,
the
distinction between pass-by-value and pass-by-reference loses some
meaning in
a language with variables of only one type : reference.

regards.

-a


#14

On 12/6/05, Peter F. removed_email_address@domain.invalid wrote:

[John] Try these defs on for size :
With pointers, we can pass the values ‘by reference.’ Passing by reference
means that we’ll pass the addresses of the variables instead of the values.
pass-by-value vs. pass-by-reference

Yes, I understand the C concepts involved and the difference between
value and reference in that regard (not sure why you think I didn’t).
However, I think one of the reasons this is a confusing issue for
people starting with Ruby that actually have previous experience with
C-like languages is that Ruby is not C.

OK, I’m far from an expert on C, and this is based on my
understanding; so if anyone notices any glaring errors, please correct
me.

In C, when you have “int a = 1;”, the value of a is 1 (a primitive
type). In Ruby, when you have “a = 1”, the value of a is actually a
reference to an instance of Fixnum which represents the integer 1.
Ruby has_no_primitive_types (ok, it’s implimented in C, so they do
exist behind the scenes; but there is no way to access a pure
primitive type within your Ruby code).

In C, when you create a variable, you reserve a specific address-space
in memory for that variable. That variable “knows” two things about
itself depending on how you use it (not quite – this is simplified);
it knows what its value is (what the contents of that memory space
is), and it knows its physical memory address (the pointer). If you
do:

int a = 1;
int b = a;

each variable reserves a separate area in memory. The first line
reserves space for the variable a and puts the value of the integer 1
in that memory space. The second line reserves space for the variable
b and then copies the value from a’s memory space into b’s memory
space.

In the following Ruby code:

a = 1
b = a

the first line reserves memory space (behind the scenes in the code
for the Ruby interpreter) for an instance of Fixnum and creates a new
instance of Fixnum with the value of 1. It then assigns a reference to
that instance of Fixnum to the variable a. However, the second line
does not create a new Fixnum address space in memory. The second line
simply tells the variable b to reference the same object that variable
a currently references. This is similar to (but not exactly the same
as) the following C code:

int x = 1; /* this (sort of) happens behind the scenes in Ruby */
int a = &x;
int b = a;

The difference is that, since Ruby doesn’t have explicit pointers, any
methods invoked on the a or b variables are automatically dereferenced
and called on the actual Fixnum object those variable point to (I
guess you could say the “pointer” is both implicit and unavoidable).
In C, you would have to specifically dereference the variable,
otherwise you would be operating on the memory address instead of the
contents of that memory space.

In C, whenever you use the assignment operator, you are basically
saying "replace the contents of the memory pointed to by the lhs with
the value on the rhs. In contrast, when you use the assignment
operator in Ruby, you are saying “replace the reference to the object
(essentially a memory space) being pointed to by the lhs with a
reference to the object (again, essentially a memory space) being
pointed to by the rhs”.

Does that make any kind of sense? (Perhaps it’s devolved to rambling
at this point.)


Regards,
John W.
http://johnwilger.com


Alice came to a fork in the road. “Which road do I take?” she asked.
“Where do you want to go?” responded the Cheshire cat.
“I don’t know,” Alice answered.
“Then,” said the cat, “it doesn’t matter.”

  • Lewis Carrol, Alice in Wonderland

#15

On Tue, 6 Dec 2005, John W. wrote:

OK, I’m far from an expert on C, and this is based on my
understanding; so if anyone notices any glaring errors, please correct
me.

In C, when you have “int a = 1;”, the value of a is 1 (a primitive
type). In Ruby, when you have “a = 1”, the value of a is actually a
reference to an instance of Fixnum which represents the integer 1.
Ruby has_no_primitive_types (ok, it’s implimented in C, so they do
exist behind the scenes; but there is no way to access a pure
primitive type within your Ruby code).

ints in ruby are not boxed. when you say

a = 1

a has 31 bits which are 1 and 1 bit that marks the word as not
being a
reference but an immeadiate value.

ints are, in fact, primitive types. the only reason you can say
-42.abs is
that ruby stores all the methods of Fixnum is a special place that is
shared
by all ints. that is why you can do this

 harp:~ > cat a.rb
 a = []

 class << a
   def foo
     42
   end
 end

 p a.foo


 harp:~ > ruby a.rb
 42

but not this

 harp:~ > cat a.rb
 a = 42

 class << a
   def foo
     42
   end
 end

 p a.foo


 harp:~ > ruby a.rb
 a.rb:3: no singleton class for Fixnum (TypeError)

regards.

-a

===============================================================================
| ara [dot] t [dot] howard [at] noaa [dot] gov
| all happiness comes from the desire for others to be happy. all misery
| comes from the desire for oneself to be happy.
| – bodhicaryavatara


#16

On 12/6/05, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

On Tue, 6 Dec 2005, John W. wrote:

Ruby has_no_primitive_types (ok, it’s implimented in C, so they do
exist behind the scenes; but there is no way to access a pure
primitive type within your Ruby code).

ints are, in fact, primitive types. the only reason you can say -42.abs is
that ruby stores all the methods of Fixnum is a special place that is shared
by all ints.

You are, of course, correct. I probably should have used strings in
those examples (I think the practical effect is the same either way,
but I admit that my example was technically incorrect).

I hadn’t realized that about Fixnum – I think what threw me off was
the fact that you would get the same value for #object_id. On further
investigation, it would seem that integers always have the same
object_id for a given value.

a = 1
b = a

a.object_id #=> 3
b.object_id #=> 3

a = 1
b = 1

a.object_id #=> 3
b.object_id #=> 3

1.object_id #=> 3

So let’s say I do

a = 1
b = 1
c = 1
d = 1

Does Ruby store 4 different copies of 1 in memory (128 bits of memory
used), or does it only store 1 copy and cause all 4 variables to
reference that copy (32 bits of memory used). Since 1 can never be
anything except 1, I would think that many programs would see a
significant improvement in memory usage if specific integers were only
stored once in memory, but perhaps that would cause a decrease in
execution speed (I have no idea)?


Regards,
John W.
http://johnwilger.com


Alice came to a fork in the road. “Which road do I take?” she asked.
“Where do you want to go?” responded the Cheshire cat.
“I don’t know,” Alice answered.
“Then,” said the cat, “it doesn’t matter.”

  • Lewis Carrol, Alice in Wonderland

#17

On Tue, 6 Dec 2005, John W. wrote:

You are, of course, correct. I probably should have used strings in
those examples (I think the practical effect is the same either way,
but I admit that my example was technically incorrect).

i thought that might have been the case :wink:

a = 1
b = 1
c = 1
d = 1

Does Ruby store 4 different copies of 1 in memory (128 bits of memory used),
or does it only store 1 copy and cause all 4 variables to reference that
copy (32 bits of memory used).

but a reference is, itself, 32 bits :wink: so storing 4 references to 1
would
require 128 bits of memory plus 32 for the actual ‘1’.

Since 1 can never be anything except 1, I would think that many programs
would see a significant improvement in memory usage if specific integers
were only stored once in memory, but perhaps that would cause a decrease in
execution speed (I have no idea)?

so, since storing the address of 1 takes the same space as storing 1 (4
bytes
on most platforms) there really can’t be any savings in space. but
storing 1
directly (un-boxed ints) defintely gives an execution speed boost.

regards.

-a

===============================================================================
| ara [dot] t [dot] howard [at] noaa [dot] gov
| all happiness comes from the desire for others to be happy. all misery
| comes from the desire for oneself to be happy.
| – bodhicaryavatara


#18

On 7/12/2005, at 8:24 AM, Kent S. wrote:

There’s a strong confusion of what exactly pass-by-reference means.
I always
thought that if a language supports pass-by-reference semantics,
then when
you define a method, one or several parameters can be declared as OUT
parameters.

That’s a completely different thing all together, and not needed in
Ruby, I’ll explain below.

The difference is simple if you understand pointers and C function
calls. Pass by value means that the actual value - the number - gets
copied in to a new memory space for the function, in pseudocode:

int i = 1; // Memory address ‘i’ contains the value 1
int r = add_one(i); // Go to function add_one, value 1 is sent,
memory address r is then set to 2
int add_one(int q) { // Memory address ‘q’ now contains 1
return q+1; // After this memory address ‘return’ for want of a
better description contains 2
}
So i and r are completely separate, change either one and the other
won’t be affected.

This is pass by reference, again in c-ish pseudocode. The memory
address is passed around so the value itself never gets copied.

int* i = 1; // Memory space ‘i’ contains the address of a memory
address that contains 1;
add_one(i); // Go to function add_one, the value passed is the memory
address.
void add_one(int* q) { // Memory address q contains the memory
address from i, this is copied.
*q = *q + 1; // The memory address referenced by q is now set to 2.
This memory address is also referenced by i, so *i is now 2.
}
In this case only one value is used - *i - but references to it are
passed around. All OO languages work like this, but not all objects
can be modified. Here’s another pseudocode example, in Ruby-ish.

i = 1 # i is a reference to an object that behaves like the integer
‘1’. Wordy huh?
add_one(i) # Passes the reference to i in to add_one
def add_one® # r is a reference to the same object referenced by i
r = r + 1 # Integers are immutable, so r is now a pointer to a NEW
object representing ‘2’. r has changed
end

If i was to change when r does then i would have to be a reference to
a reference, and that reminds me of the OS 9 memory manager… Also,
if Ruby was pass-by-value then r would contain a brand new object,
and that reminds me of PHP4, not good.

Pass by reference to return values is only useful for languages
without a native array type and parallel assignment. If you think
it’ll boost speed then you’re thinking on the wrong tracks, you
should look to other areas first, and do a quick search for
‘premature optimisation’.

Here’s a Ruby example of something that has to return two results.
Anything could be returned, they’re all just objects.

def crazy_add(q, r, s)
[q+s, r+s]
end

i, j, k = 2, 3, 4 # i = 2, j = 3, k = 4. Remember the construct.
a, b = crazy_add(i, j, k) # a = 6, b = 7

The key point people seem to be missing is that integers in Ruby are
immutable objects - they can never be changed, but if strings or some
other object was used then modifying in place is easily possible. I
know there are some differences between a normal object and an
Integer for speed reasons, but just think of them as any other
object. In Python strings are also immutable, so a similar issue
could be found.

I hope this does something to clarify the issue.


Phillip H.
removed_email_address@domain.invalid


#19

Ara,

There’s a strong confusion of what exactly pass-by-reference means. I
always
thought that if a language supports pass-by-reference semantics, then
when
you define a method, one or several parameters can be declared as OUT
parameters.

For example,

[this is a pseudo-code]

def amethod( ref a )
a = “two”
end

a = “one”
amethod(a)

p a # => “two”

Here I’m not using String#replace method. Otherwise the initial object
“one”
stays the same but the content of the object changes which isn’t
pass-by-reference goal.

Kent.


#20

On 12/6/05, Peter F. removed_email_address@domain.invalid wrote:

removed_email_address@domain.invalid

Joyeux Noël

Peter F.

I want to try my definition on again. My point to posting it was to
clarify
the difference between the “value” of a primitive and the “address” of a
pointer-referenced object.

Ruby’s Object and all descendants (not Fixnum) are pointer-referenced
objects. Ruby’s treatment of Fixnum sounds to be (bluntly, (grossly?))
a
cached-processing algorithm for Fixnum… the same reference process is
used
for Object+Fixnum and an if…then on the high-bit tells the process path
to
use the Fixnum cached-instance on the value of the pointer(31-bits).

A. does this explanation jive?
B. I agree with the above posts… this sub-thread has nothing to do
with
wether ruby supports “pass-by-reference” (it does not).
C. I won’t bother you any more with my sub-guru antics.