Рубин: рекурсивный метод

def reverse_append(arr, n)  
    return arr if n < 0 
    reverse_append(arr, n-1)
    arr << n
    arr
end 

reverse_append([],4) #=> [0, 1, 2, 3, 4]

Я не могу понять этот рекурсивный метод. Это производит массив от 0 до n.

Может кто-то объяснить это мне?

 sawa29 июн. 2016 г., 18:16
Как вы думаете, где это имеет значение?
 Karen B29 июн. 2016 г., 17:58
Лучший способ изобразить, что делает рекурсивная функция, - это часто добавлять вывод для каждой итерации. Попробуйте добавитьputs arr.inspect прямо над последнимarr строка в методе и запустить.
 the Tin Man29 июн. 2016 г., 18:18
Пожалуйста, будьте осторожны, задавая вопросы «объясните мне». Широко открытые вопросы «объясни мне весь код» слишком широки и не показывают каких-либо исследований / попыток понять код. «объяснить одну конкретную строку», после исследования и объяснения того, как исследование не помогло, гораздо менее широко и более вероятно, что будет тематическим. Я не голосовал против и не голосовал за закрытие, потому что это небольшой кусок кода.

Ответы на вопрос(3)

Решение Вопроса
Методreverse_append([],4) называетсяпоскольку4 >= 0,return заявление не вызывается.Методreverse_append([],3) называется.поскольку3 >= 0,return заявление не вызывается.Методreverse_append([],2) называется.поскольку2 >= 0,return заявление не вызывается.Методreverse_append([],1) называется.поскольку1 >= 0,return заявление не вызывается.Методreverse_append([],0) называется.поскольку0 >= 0,return заявление не вызывается.Методreverse_append([],-1) называется.поскольку-1 < 0, массив ([]) возвращается.Мы поднимаемся на один уровень в нашем стеке вызовов, гдеn = 0 а такжеarr = [].arr << n а такжеarr возвращается, так что теперьarr = [0].Мы поднимаемся на один уровень в нашем стеке вызовов, гдеn = 1 а такжеarr = [0].arr << n а такжеarr возвращается, так что теперьarr = [0, 1].Мы поднимаемся на один уровень в нашем стеке вызовов, гдеn = 2 а такжеarr = [0, 1].arr << n а такжеarr возвращается, так что теперьarr = [0, 1, 2].Мы поднимаемся на один уровень в нашем стеке вызовов, гдеn = 3 а такжеarr = [0, 1, 2].arr << n а такжеarr возвращается, так что теперьarr = [0, 1, 2, 3].Мы поднимаемся на один уровень в нашем стеке вызовов, гдеn = 4 а такжеarr = [0, 1, 2, 3].arr << n а такжеarr возвращается, так что теперьarr = [0, 1, 2, 3, 4].Наконец, возвращается метод «верхнего уровня», и мы получаем наш конечный результат.
 13aal29 июн. 2016 г., 19:13
Есть ли действительно так много шагов? o.o
 Tom Lord30 июн. 2016 г., 00:28
@ 13aal Я думаю, что самая большая концептуальная трудность, с которой люди сталкиваются, впервые узнавая о рекурсивных функциях, заключается в простом прохождении примера, строка за строкой, и отслеживании того, что на самом деле происходит. Так что да, мой ответ, возможно, немного выше; но я надеюсь, что это также побудит читателей пройти через этот код, чтобы понять основную концепцию.

является проверка, если n <0, что не так. Если это не 0, обратное добавление с [], 3 и добавление к этому массиву числа, а затем возвращает массив.

Таким образом, он принимает массив, добавляет 4 к нему после того, как он прошел через этап работы с[], 3, [], 2, [],1 а также[], 0, Таким образом, первый успешный вызов - это просто возврат массива, когда он становится ниже 0, затем добавляется 0, затем добавляется один, затем 2, затем 3 и, наконец, добавляется исходный вызов с 4.arr << n.

который вы можете добавить ко многим редакторам под названием "Видеть значит верить", который позволяет вам видеть, что происходит во время выполнения кода:

def reverse_append(arr, n)  
  return arr if n < 0 # => false, false, false, false, true
  reverse_append(arr, n-1) # => [], [0], [0, 1], [0, 1, 2]
  arr << n # => [0], [0, 1], [0, 1, 2], [0, 1, 2, 3]
  arr # => [0], [0, 1], [0, 1, 2], [0, 1, 2, 3]
end 

reverse_append([], 3) # => [0, 1, 2, 3]

Однако с таким именем, как "reverse_append", кажется, что вы должны увидеть результат, который убывает в значениях:

def reverse_append(arr, n)  
  return arr if n < 0 # => false, false, false, false, true
  reverse_append(arr, n-1) # => [], [0], [1, 0], [2, 1, 0]
  arr.unshift n # => [0], [1, 0], [2, 1, 0], [3, 2, 1, 0]
  arr # => [0], [1, 0], [2, 1, 0], [3, 2, 1, 0]
end 

reverse_append([], 3) # => [3, 2, 1, 0]

В любом случае, есть много более простых способов создать такой массив, не полагаясь на рекурсию:

[*0..3] # => [0, 1, 2, 3]
(0..3).to_a # => [0, 1, 2, 3]

[*0..3].reverse # => [3, 2, 1, 0]
(0..3).to_a.reverse # => [3, 2, 1, 0]

Ваш ответ на вопрос