0

This is a very weird one.

So I have a class LibSystem

class LibSystem
  attr_accessor :borrower
  attr_reader :books
  def initialize(book_inventory = [])
    @borrower = []
    @books = book_inventory
    @borrowed = []
  end
#...
end

From another file I do require_relative and the file which contains it. Then I do this...

#...
sys = LibSystem.new(books)
puts sys.books.length
books << Book.new("Adventure Of My New Cat", "3-598-21515-0", "3", "funny publications", "2001", [auth3], 1)
puts sys.books.length

What I expect is for the first length to be 9 (size of the array I passed to the constructor) and the second to be the same. Instead I get 9 and 10 accordingly. This seems like the instance variable inside my sys object is updating along with the array that was passed into it. This seems completely wrong to me. Am I doing anything wrong here, or is this the standard behavior? Thank you.

The title is probably inaccurate, if you have anything better, feel free to edit.

Kostas Andrianos
  • 1,551
  • 2
  • 16
  • 21

1 Answers1

1

Arrays and hashes in Ruby are by default not copied. Inside LibSystem you assign the passed book_inventory to the @books instance variable; Your new LibSystem instance just holds on the address of the existing array without copying the contents. When you used << to append to the array, you modified the same array.

It is sometimes considered a good practice to copy the arrays or dictionaries used in an initializer to avoid exactly this kind of interference, although your use case may vary.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
mattbornski
  • 11,895
  • 4
  • 31
  • 25
  • Would making a duplicate of the array and passing that, work, and above all, be a good practice? Thank you. – Kostas Andrianos May 26 '17 at 18:49
  • I would suggest instead of copying before you call, make your initializer copy the array before assigning to the instance variable - that way, regardless of how well written the code that calls your LibSystem class is, your class has an expectation that nobody will interfere with it's state. – mattbornski May 26 '17 at 18:50
  • And I would consider that to be perfectly reasonable practice. Not always the most efficient, but I will choose correctness and reliability over efficiency in nearly every application. – mattbornski May 26 '17 at 18:51
  • 1
    Check Abe Voelker's answer [here](https://stackoverflow.com/questions/1872110/is-ruby-pass-by-reference-or-by-value) – yorodm May 26 '17 at 18:53