Ruby passes parameters by value

I was convinced Ruby passes parameters by reference when you call a method. I knew there are some special cases (bool, symbols, fixnums, floats) when uses pass-by-value, but usually for objects by-reference is the default. Today I had a conversation on Stackoverflow about the topic and now I know the most object oriented languages (like C#, Java, Smalltalk) use pass-by-value, or more precisely pass-by-value-of-pointer.

In Ruby the variables are stored by uintptr_t VALUE. VALUE can have special flags to determine it’s type. Special flags are small integer, symbol, true, false, nil, Qundef. When no special flag is set, it stores a reference to an object. When you pass a parameter to a method, it passes the VALUE by-value, so the reference to the object will be copied. Consider this behaviour it can be pass-by-reference, but it’s not.

In C++ when you pass an object by reference, you do something like this:

1
2
3
4
5
void increase(int &param)
{
  int d = param + 1;
  param = d;
}
void increase(int &param)
{
  int d = param + 1;
  param = d;
}

After calling increase method with a value, the param will be increased well.

1
2
3
int num = 1;
increase(num);
// num == 2
int num = 1;
increase(num);
// num == 2

In Ruby because the VALUE is passed by value, the previous C++ like implementation works different:

1
2
3
4
5
6
7
8
9
def increase(param)
  d = param + 1
  param = d
end
 
num = 1
increase(num)
 
# num == 1
def increase(param)
  d = param + 1
  param = d
end

num = 1
increase(num)

# num == 1

param = d in increase method will copy a new reference to the VALUE, so param will reference a new object. After returning from increase both the d and the new param will be freed, and the original value of param will be referenced by num, 1.

So that’s why we say Ruby uses pass-by-value when calling a method with an object!