Почему эта рекурсия НЕ бесконечна?

Мы с друзьями работаем над некоторыми базовыми упражнениями Ruby, чтобы почувствовать язык, и мы столкнулись с интересным поведением, которое мы пока не можем понять. По сути, мы создаем тип данных tree , в котором есть только один класс, узел , который содержит ровно одно значение и массив из нуля или более узлов . Мы используем средство запуска тестов autospec rspec . В какой-то момент мы начали писать тесты, запрещающие бесконечную рекурсию (круговая древовидная структура).

Вот наш тест:

it "breaks on a circular reference, which we will fix later" do
  tree1 = Node.new 1
  tree2 = Node.new 1
  tree2.add_child tree1
  tree1.add_child tree2
  (tree1 == tree2).should be_false
end

Вот класс Node:

class Node
  attr_accessor :value
  attr_reader :nodes

  def initialize initial_value = nil
    @value = initial_value
    @nodes = []
  end

  def add_child child
    @nodes.push child
    @nodes.sort! { |node1, node2| node1.value <=> node2.value }
  end

  def == node
    return (@value == node.value) && (@nodes == node.nodes)
  end
end

Мы ожидаем, что последняя строка теста приведет к бесконечной рекурсии пока стек не переполнится, потому что он должен постоянно сравнивать дочерние узлы друг с другом и никогда не находить листовой узел. (У нас сложилось впечатление, что оператор == в массиве будет перебирать массив и вызывать == для каждого дочернего элемента на основе страницы массива RubyDoc .) Но если мы бросим помещает в метод == , чтобы увидеть, как часто он вызывается, мы обнаруживаем, что он вызывается ровно три раза, а затем тест проходит.

Что нам не хватает?

Edit : Обратите внимание, что если мы заменим be_false в тесте на be_true , то тест не пройдёт. Таким образом, он определенно считает, что массивы не равны, он просто не повторяется по ним (кроме трех разных вызовов == ).

9
задан David 12 September 2010 в 09:33
поделиться