7

The following behavior looks to me like the assign method is processing visited by value, whereas the append method is treating it as a reference:

class MyClass
  def assign(visited)
    visited += ["A"]
  end
  def append(visited)
    visited << "A"
  end
end

instance = MyClass.new
visited = []

instance.assign(visited)
visited # => []

instance.append(visited)
visited # => ["A"]

Can someone explain this behavior?

This is not a question about whether Ruby supports pass by reference or pass by value, but rather about the example provided below, and why two methods that purportedly do the same thing exhibit different behaviors.

FloatingRock
  • 6,741
  • 6
  • 42
  • 75
  • Possible duplicate of [Ruby - Parameters by reference or by value?](http://stackoverflow.com/questions/22827566/ruby-parameters-by-reference-or-by-value) – Thomas R. Koll Apr 28 '17 at 11:34
  • @ThomasR.Koll I don't think that question is related. This example (apparently) exhibits both pass-by-reference and pass-by-value behavior – FloatingRock Apr 28 '17 at 11:35

2 Answers2

3

You redefine local variable in the first method.

This is the same as

visited = []
local_visited = visited
local_visited = ['A']
visited
# => [] 

And in the second method:

visited = []
local_visited = visited
local_visited << 'A'
visited
# => ["A"] 
mikdiet
  • 9,859
  • 8
  • 59
  • 68
  • Coupled with [this](http://stackoverflow.com/questions/22827566/ruby-parameters-by-reference-or-by-value), it makes perfect sense. Thanks! – FloatingRock Apr 28 '17 at 11:56
1

Here's a modified version of MyClass#assign which mutates visited:

class MyClass
  def assign(visited = [])
    visited[0] = "A"
  end
  def append(visited = [])
    visited << "A"
  end
end

instance = MyClass.new
visited = []

instance.assign(visited)
p visited # => ["A"]

visited = []
instance.append(visited)
p visited # => ["A"]
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
  • Hmm, I don't get why `visited[0] = "A"` mutates but not `visited += ["A"]`? – FloatingRock Apr 28 '17 at 13:33
  • 1
    @FloatingRock `visited += ['A']` is actually `visited = visited + ['A']`, so it defines a new object. `visited[0] = 'A'` keeps the same object, but modifies its first element. – Eric Duminil Apr 28 '17 at 13:41
  • Ah, hence the difference between `<<` and `+=`. The `<<` works because it makes changes in place. – FloatingRock Apr 28 '17 at 13:43