Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Ruby pass-by-value or pass-by-reference? [duplicate]

I am basically a java developer. I am working in ruby for about an year. Unlike java, Ruby is a pure object oriented programming language. Here comes a doubt. Is it pass-by-value or pass-by-reference? Java works as pass-by-value: "When passing primitives, I see that the value is duplicated and passed to the method. But incase of Objects, the reference is duplicated and passed to the method. The reference contains the location of the object in the heap. During the method call, only the location of the object is passed. So no duplicate objects are created. The same object is modified."

But when I tried the below ruby code snippet, I got the same results as I got in Java: "The numbers work like a primitive (like in java) during a method call whereas the array works as perfect references like in java". Now, I am confused. If everything in ruby are objects, then why the number objects are duplicated during the method call?

class A
  def meth1(a)
    a = a+5
    puts "a inside meth1---#{a}"
  end

  def meth2(array)
    array.pop
    puts "array inside meth2---#{array}"
  end
end


obj1 = A.new
aa=5
obj1.meth1(aa)
puts "aa-----#{aa}"

arr = [3,4,5]
obj1.meth2(arr)
puts "arr---#{arr}"

Results:

a inside meth1---10

aa-----5

array inside meth2---34

arr---34

like image 622
Arun Avatar asked Nov 27 '22 02:11

Arun


1 Answers

Ruby uses pass-by-value, or more precisely, a special case of pass-by-value where the value being passed is always a pointer. This special case is also sometimes known as call-by-sharing, call-by-object-sharing or call-by-object.

It's the same convention that is used by Java (for objects), C# (by default for reference types), Smalltalk, Python, ECMAScript/JavaScript and more or less every object-oriented language ever created.

Note: on all existing Ruby implementations Symbols, Fixnums and Floats are actually passed directly by value and not with an intermediary pointer. However, since those three are immutable, there is no observable behavioral difference between pass-by-value and call-by-object-sharing in this case, so you can greatly simplify your mental model by simply treating everything as call-by-object-sharing. Just interpret these three special cases as internal compiler optimizations that you don't need to worry about.

Here's a simple example you can run to determine the argument passing convention of Ruby (or any other language, after you translate it):

def is_ruby_pass_by_value?(foo)
  foo.replace('More precisely, it is call-by-object-sharing!')
  foo = 'No, Ruby is pass-by-reference.'
  return nil
end

bar = 'Yes, of course, Ruby *is* pass-by-value!'

is_ruby_pass_by_value?(bar)

p bar
# 'More precisely, it is call-by-object-sharing!'
like image 140
Jörg W Mittag Avatar answered Dec 11 '22 00:12

Jörg W Mittag