У меня есть приложение Ruby, которое я разрабатываю, по какой-то причине не работает должным образом при использовании рекурсивной функции, которая содержит блок внутри, чтобы возвращать значение из другого класса (проще увидеть в примере кода ниже). Странно то, что когда я создал минимальный образец, чтобы попытаться выяснить, что происходит, образец работает так, как ожидалось. Пример:ruby recursive loop с конструкцией возврата субблока
require 'json'
class Simple
attr_accessor :name, :children
def initialize(name,children=nil)
@name = name
@children = children
end
end
a = Simple.new('A')
b = Simple.new('B',[a])
c = Simple.new('C',[b])
d = Simple.new('D')
e = Simple.new('E',[d])
f = Simple.new('F')
g = Simple.new('G',[e,f])
foo = [c,e,g]
def looper(d)
holder = nil
d.each do |item|
# puts item.name
if item.name == 'D'
holder = Simple.new('Z',[])
elsif !item.children.nil?
holder = looper(item.children)
end
end
return holder
end
bar = looper(foo)
puts "Returned from looper: #{bar.name}"
В моем фактическом коде я в конечном итоге с помощью переменного экземпляра класса, чтобы получить ответ (который также работает в примере коде). Пример фрагмента функции сверху модифицирована в другой схеме:
def looper(d)
holder = nil
d.each do |item|
# puts item.name
if item.name == 'D'
@holder = Simple.new('Z',[])
elsif !item.children.nil?
looper(item.children)
end
end
@holder
end
Так что мой вопрос, является это хорошая практика, чтобы использовать переменную экземпляра? Любые побочные стороны для этого, поскольку он работает для моего фактического кода, тогда как в первом примере шаблона нет?
благодарит за отзыв. На моей Windows 7, установке Ruby 1.9, обе версии возвращают тот же результат. Вы действительно видите различия или просто ожидаете? Это одна из областей Ruby, которую я нахожу наиболее запутанной, потому что то, что я вижу в моем простом примере, фактически не работает в моем полноценном приложении :( – bicarbon8
На самом деле вы правы, я неправильно читаю свой вывод IRB и первый пример возвращает объект, который вы хотите. Однако потенциал для него фактически возвращает «nil», и мое утверждение о необходимости наличия точек останова остается в силе - ваши два примера кода кода ведут себя по-разному из-за возможности «держателя» 'для установки на' nil' после того, как вы нашли значение, поскольку вы продолжаете поиск –
Простейший способ поставить мой последний комментарий - посмотрите на значение looper (foo.reverse) для двух вариантов функции. см. пример того, что происходит в вашем производственном коде, и хороший пример того, почему лучшие тесты включают изменения входных данных. –