1

Excuse I am newbie in ruby.

My problem is about argument passes by value and reference.

I am coding this method

def show_as_tree(parents)
  array = []
  iterate_categories(parents, array)
end

def iterate_categories(parents, array)
  parents.each do |p|
    #return p.description or "-#{p.description} if the node is root or not
    p.description = category_name(p)

    #add to array
    array << p

    #call iterate categories with children of parent node and same array
    iterate_categories(p.children, array)
  end
end

however the array content is only the parent nodes.

I need understand the ruby mechanism for references and how could fix my problem?

1
  • You can use object_id method on any object to get answer for your question. Commented May 19, 2011 at 18:34

3 Answers 3

1

I'm pretty sure Ruby just creates a copy of your array. Therefore what you should be doing is having

array << iterate_categories(p.children, new_array)

And return your array at the end of the function.

Just did a quick example: (Updating code based on Wayne Conrad's answer… it is correct)

class Person
  attr_accessor :name, :children
end

class Test

  def iterate_categories(parents,array)
    parents.each do |p|
      array << p.name
      if !p.children.nil?
        iterate_categories(p.children,array)
      end
    end
  end

  def iterate_categories_test
    p1 = Person.new
    p1.name = "Bob"

    p2 = Person.new
    p2.name = "Joe"

    p3 = Person.new
    p3.name = "Ann"

    p4 = Person.new
    p4.name = "John"

    p1.children = [p2,p3]
    p3.children = [p4]

    array = []
    iterate_categories([p1],array)
    puts array
  end
end

Then:

>> a = Test.new
>> a.iterate_categories_test
Bob
Joe
Ann
John
=> nil

Hopefully that helps.

Sign up to request clarification or add additional context in comments.

3 Comments

Actually, ruby passes arguments by reference, but also performs a copy-on-write: ruby-forum.com/topic/41160
@Kris, I think that's incorrect. Ruby does not do copy-on-write. Variables are (conceptually, at least) references. When you call a method, references to the values you pass in the argument list are assigned to the arguments. And a mutable object can have its state changed through messages (method calls) sent to it via its reference. That's pretty much it.
This solution works not because ruby was copying array (it wasn't), but because it properly returns array from the function.
1

Your show_as_tree method should return the array.

def show_as_tree(parents)
  array = []
  iterate_categories(parents, array)
  array
end

Without array as the last line, the return value of show_as_tree is the return value of iterate_categories, which happens to be parents. That's why it looks like only parents is getting added to array. That's an illusion: It was parents being returned, not array.

Ruby does not make copies of its arguments. It passes references by value. That means it is the same array being acted upon throughout your functions.

1 Comment

Good to know. Learn something new every day. Thanks.
0

I don't quite get the code, the formatting seems all wrong but I'll try to help.

When you pass an argument to ruby, it seems to give the method a copy, not a reference. Fortunately, you don't need to worry about that, as ruby lets you return multiple things in one call.

For example, in irb I ran something like this:

ruby-1.9.2-p180 :005 > def stuff(a, b)
ruby-1.9.2-p180 :006?>   c = a + b
ruby-1.9.2-p180 :007?>   [c, a]
ruby-1.9.2-p180 :008?>   end
 => nil 
ruby-1.9.2-p180 :009 > a, b = stuff(1, 2)
 => [3, 1] 
ruby-1.9.2-p180 :010 > a
 => 3 
ruby-1.9.2-p180 :011 > b
 => 1

That way you can easily return multiple values without problem

I hope I answered your question.

1 Comment

Ruby does copy its arguments, but what it is copying are references.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.