现在,因为我们're going to be writing a recursive method, we need to think of our base case. We want exactly nine circles drawn. Let'调用这个最大圈数 max . 我们的基本情况,当我们突破"loop"时,将是 max 迭代,或 (= iterations max) .
(foldl hc-append (blank) ...) --->
(hc-append o (hc-append o (hc-append o (hc-append o (hc-append o (hc-append o (hc-append o (hc-append o (hc-append o (blank))))))))))
在这里,我们重复操作(列出'Duck结果)初始值'Go!积累结果 . for / fold 's implementation is based on the recursive process that Roddy describes, so once you have the fundamentals down, you'我知道足够用于/折叠舒适 .
4 回答
你需要意识到的第一件事是,在Racket中“循环”实际上只是递归 . 在这种情况下,您希望将一堆绘图调用链接在一起 . 如果我们写出来,我们的目标是:
我假设我们所有的圈子都是相同的半径 .
现在,因为我们're going to be writing a recursive method, we need to think of our base case. We want exactly nine circles drawn. Let'调用这个最大圈数
max
. 我们的基本情况,当我们突破"loop"时,将是max
迭代,或(= iterations max)
.现在为递归本身 . 我们已经知道我们需要传递至少两个变量,当前迭代
iterations
和最大迭代max
. 如果你看一下上面的代码,你会发现所有"loops"中的重复元素是(circle 10)
. 现在有很多方法可以传递它 - 有些人会选择仅仅通过半径 - 但我认为最简单的方法是传递圆圈的图形 .最后,我们还要传递到目前为止我们所做的图片 . 也就是说,当我们向我们的链附加一个圆圈时,我们需要将它传递回递归方法,以便我们可以继续追加 .
现在我们已经得到了平方,我们可以定义递归方法的结构,我们称之为
circle-chain-recursive
:我们方法的"guts"将是
if
. 如果我们已达到最大迭代次数,则返回输出 . 否则追加另一个圆圈,递增iteration
,然后再次调用该方法 .我个人不喜欢直接调用这样的递归循环方法,所以我会编写一个这样的辅助方法:
现在,如果我想要一个半径为10的9个圆的系列,我所要做的就是调用
(circle-chain 9 10)
.你会注意到我传递了
(circle 0)
作为名为output
的参数 . 这是因为hc-append
方法需要pict
参数 . 既然我们对slideshow/pict
库不太熟悉就知道了 .我希望稍微澄清一下 .
Racket中有三种循环样式:
#1 for循环风格
此样式使用“球拍指南”第11章中描述的语法"Iterations and Comprehensions" . 它看起来像这样:
在这种风格中,在for之后的第一个括号中定义了循环的临时变量 . 在我的例子中有一个这样的变量叫做result . 然后定义迭代变量以及它们迭代的内容 . 所以在这里,我循环遍历0到8的数字 . 循环体对每个i运行一次,每次将结果分配给结果,循环的最终值是结尾处的结果值 .
#2 Map 和折叠样式 .
此样式在Section 3.8 of the Guide中描述 . 它看起来像这样:
此代码首先列出9个圆圈:
列表符号是更详细的符号表示的简写 .
考虑foldl函数的方法是将一段数据转换为一个计算 . 它将列表作为输入,并将其转换为函数调用的集合 .
foldl函数获取列表并用第一个参数替换列表中的每个cons,并用第二个参数替换列表末尾的空 . 在示例中,我传递了hc-append函数和(空白),因此替换如下所示:
这个函数调用序列正是您希望避免手动编写的函数 . Foldl为你计算它 .
#3递归样式
这是罗迪在他的回答中描述的风格 . 作为编码风格的一般问题,如果没有简单的* for,map或fold可能,则应该只使用递归样式,例如遍历递归数据结构时 .
冷冻豌 beans 的罗迪有这个答案几乎涵盖 .
我想补充一点,因为这类事情是如此常见 - 重复一个过程并积累结果 - 在Racket语言中有一些功能可以简洁地表达这个想法 . 其中一个功能是Racket的for/fold循环 . 举个例子:
在这里,我们重复操作(列出'Duck结果)初始值'Go!积累结果 . for / fold 's implementation is based on the recursive process that Roddy describes, so once you have the fundamentals down, you'我知道足够用于/折叠舒适 .
这是一个老帖子,但它是高度阅读,因此我添加一个答案 . 使用'named let'的方法也非常方便: