计算灵丹妙药中的自然数

时间:2016-09-15 03:45:16

标签: elixir

我正在阅读“Elixir in Action”一书,我对以下示例如何运作感到难过。

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是最后一个,因为它会停止递归。

浏览此模块的控制流程将非常有用

4 个答案:

答案 0 :(得分:7)

puts调用在递归调用print后发生。因此,虽然传递的输入遵循顺序3,2,1,但puts命令将以相反的顺序执行。粗略地说,这就是它:

  1. print(3) - 原始输入
  2. print(2) - 递归调用打印(n-1)
  3. print(1) - 递归调用打印(n-1);达成基本案例
  4. 放(1)
  5. puts(2) - 完成print(2)调用
  6. puts(3) - 完成print(3)调用

答案 1 :(得分:1)

重要的是,放置一个值并进行递归调用的顺序。如果功能是

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

(注意与您的版本相比更改的顺序),您获得3⇒2⇒1输出,因为IO.puts在递归调用之前发生

答案 2 :(得分: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次递归调用,到达最后一步,然后才开始以相反的顺序打印结果。

答案 3 :(得分:-2)

检查此提案:

numeros = Enum.map(1..10, fn x -> x end)
Enum.map(numeros, fn num -> IO.puts "#{num}" end)