Who modified my local variable?

Jacob Fugal lukfugl at gmail.com
Tue Jun 13 10:31:19 MDT 2006


On 6/13/06, Shane Hathaway <shane at hathawaymix.org> wrote:
> So again, I think a better way to express your point is to say that Java
> passes primitives by value and objects by reference.  Higher level
> languages like Python do away with primitives and pass everything by
> reference.

While I can't speak -- not knowing -- to whether Java passes objects
by reference or references by value, there *is* an important
difference. For instance in Ruby, it is quite clear that references
are passed by value. The objects are *not* passed by reference.
Passing by reference and passing references by value are illustrated
by this C++ code:

  void myFunc1(int c) {
      c = 5;
      printf("in myFunc1, c = %d\n", c);
  }

  void myFunc2(int &c) {
      c = 5;
      printf("in myFunc2, c = %d\n", c);
  }

  int main(void) {
      int x = 2;
      printf("before myFunc1, x = %d\n", x);
      myFunc1(x);
      printf("after myFunc1, x = %d\n", x);
      myFunc2(x);
      printf("after myFunc2, x = %d\n", x);
      return 0;
  }

Output:

  before myFunc1, x = 2
  in myFunc1, c = 5
  after myFunc1, x = 2
  in myFunc2, c = 5
  after myFunc2, x = 5

In the call to myFunc1, c is a new variable which holds a copy of the
data that was in x. Standard pass by value. Once the call returns, x
is unchanged. In the call to myFunc2, c is a variable that refers to
the same memory location as x, so when c is assigned to, x is assigned
to as well.

But in Ruby, objects are not passed by reference, but instead all
variables *are* references, which are then passed by value. Example:
(using a string instead of an int to afford mutability; Fixnums are
immutable in Ruby):

  def my_func1(c)
    c = c.capitalize
    puts "in my_func1, c = '#{c}'"
  end

  def my_func2(c)
    c.capitalize!
    puts "in my_func2, c = '#{c}'"
  end

  x = "hello, world."
  puts "before my_func1, x = '#{x}'"
  my_func1(x)
  puts "after my_func1, x = '#{x}'"
  my_func2(x)
  puts "after my_func2, x = '#{x}'"

Output:

  before my_func1, x = 'hello, world.'
  in my_func1, c = 'Hello, world.'
  after my_func1, x = 'hello, world.'
  in my_func2, c = 'Hello, world.'
  after my_func2, x = 'Hello, world.'

So you can see from the first call that the variable is *not* passed
by reference; assigning to c has no effect on x, as it did in the C++
example. But my_func2 demonstrates that we're not passing the string
by value (copying) either, since the same object is referred to by
both c and x; mutating c with the in-place #capitalize! message
affected x as well. This is because both c and x did refer to the same
object. What c and x contain are not the object itself, but references
(pointers, basically) to the object. That reference is passed by
value, so assignment in my_func1 only overwrites the copied reference
and not the referred to object, yet my_func2 can operate on that
reference and be working with the same object.

Jacob Fugal



More information about the PLUG mailing list