2016-09-15 4 views
2

Я прохожу через Эликсир в книге действий, и я немного в тупике, как работает следующий пример.Подсчет натуральных чисел в эликсире

defmodule NaturalNums do 
    def print(1), do: IO.puts(1) 

    def print(n) do 
    print(n - 1) 
    IO.puts(n) 
    end 
end 

дает этот вывод:

iex(2)> NaturalNums.print(3) 
1 
2 
3 

Что я запутался о том, как этот модуль рассчитывает вверх от 1, а не вниз от 3. Если не 3 быть распечатаны первым, затем 2 и затем 1 ? 1 является последним, потому что он останавливает рекурсию.

Прогулка по потоку управления этого модуля будет полезно

ответ

7

puts вызов происходит после рекурсивного вызова print. Таким образом, в то время как переданные входные данные выполняют порядок 3,2,1, команда puts будет выполнена в обратном порядке. Грубо говоря, это то, как он идет:

  1. печать (3) - оригинальный вход
  2. печати (2) - рекурсивный вызов печати (п-1)
  3. печати (1) - рекурсивный вызов печати (п -1); базовый случай достиг
  4. пут (1)
  5. пут (2) - завершает печать (2) называют
  6. пут (3) - завершает печать (3) называют
+0

спасибо за это. но как только базовый случай будет достигнут - как функция продолжит работу, а затем продолжит отсчет вверх? – metersk

1

Каких вопросов, является порядок ввода ценности и выполнение рекурсивного вызова. Если функция была

def print(n) do 
    IO.puts(n) 
    print(n - 1) 
end 

(обратите внимание на изменившийся порядок по сравнению с вашей версией), вы получали 3⇒2⇒1 выход, потому что IO.puts должно было случиться перед рекурсивный вызов.

+0

Я думаю, что это даже хвост рекурсивный ... – Haito

1

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

defmodule NaturalNums do 
    def print(1) do 
    IO.puts "Last step (n=1)" # <-- debugging 
    IO.puts(1) 
    end 

    def print(n) do 
    IO.puts "Starting recursive call (n=#{n})" # <-- debugging 
    print(n - 1) 
    IO.puts "After recursive call (n=#{n})" # <-- debugging 
    IO.puts(n) 
    end 
end 

NaturalNums.print(5) 

Вот выход:

Starting recursive call (n=5) 
Starting recursive call (n=4) 
Starting recursive call (n=3) 
Starting recursive call (n=2) 
Last step (n=1) 
1 
After recursive call (n=2) 
2 
After recursive call (n=3) 
3 
After recursive call (n=4) 
4 
After recursive call (n=5) 
5 

Как вы можете видеть, первое это делает 4 рекурсивных вызовов, достигает последний шаг и только затем начните печатать результаты в обратном порядке.

+0

спасибо за этот тщательный ответ. мой вопрос: как это происходит? Тогда начните печатать результаты в обратном порядке ».? я не вижу никакого механизма, который бы сохранял результаты или продолжал цикл после того, как базовый случай был достигнут – metersk