我正在尝试学习使用 Clojure for the Brave and True (CFTBAT)这本书进行编程。在速成课程结束时,作者让我们编写一个小程序来说明Clojure中的循环。为了解释程序的循环和递归部分here,作者使用loop
编写了一个较小的示例,然后显示可以用正常的函数定义替换loop
。
这是我无法理解的正常功能定义示例。这是代码:
(defn recursive-printer
([]
(recursive-printer 0))
([iteration]
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recursive-printer (inc iteration)))))
(recursive-printer)
我不理解代码,因为我看不到函数recursive-printer
的参数在哪里。在Clojure中,函数的参数应该在括号中,而正文在括号中。因此,在此示例中,参数将是空参数[]
和iteration
。但是,为什么他们也在括号之间?
什么是(recursive-printer 0)
它是函数调用,函数调用自身吗?
如果有人能解释我这段代码是如何工作的,那将非常感激。
答案 0 :(得分:2)
在clojure中,您可以定义一个函数,使其可以使用不同数量的函数 参数例如
(defn foo []
....)
是一个不带参数的函数。它就像这样......
(foo)
(defn foo [x]
...)
是一个带1个参数的函数。它可以被称为
(foo :a)
但有时,您可能想要定义一个取零或1的函数 论点。为此,您使用稍微不同的格式
(defn foo
([] ;no argument form
...)
([x] ;single argument form
...))
一个常见的习惯用法是在递归函数定义中使用零参数形式 并包括一个“累加器”#39;论证形式作为主要部分 功能。所以,看看你的例子,你有
(defn recursive-printer
([] ; zero argument form
(recursive-printer 0))
([iteration] ; 1 argument form
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recursive-printer (inc iteration)))))
(recursive-printer)
当你调用(递归打印机)时,它会调用第一个表单(零参数 形成)。该形式又使用单个参数0调用该函数 调用第二种形式。
第二种形式首先打印出参数,然后测试是否存在 大于3,在第一次调用中它不是0,所以它执行 '否则'语句,使用新参数进行递归调用 当前参数增加1.现在您的参数为1并且打印出来 出。测试仍然是假的,因为1不是> 3,所以再次调用该函数 随着参数增加1,即2.在此调用中,打印2,测试为 仍然不比三个更大,所以用参数再次调用该函数 在此调用中,打印3并且测试仍然不是> 3。 3,所以 参数增加到4,函数再次调用4作为 论点。打印值4,但是此时间4> 3,所以字符串"再见"是 打印,因为这是终止条件,没有进一步的递归调用 制作并且堆栈展开并且函数终止。
答案 1 :(得分:1)
我们可以放弃零度:
(defn recursive-printer [iteration]
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recursive-printer (inc iteration))))
...并使用显式0
参数调用该函数:
(recursive-printer 0)
0
1
2
3
4
Bye!
=> nil
这让我们专注于递归。由于递归调用是最后一件事(在尾部位置),我们可以改为使用recur
:
(defn recursive-printer [iteration]
(println iteration)
(if (> iteration 3)
(println "Bye!")
(recur (inc iteration))))
......具有完全相同的效果。
我想,多余的东西会让事情变得混乱。