scheme递归
主要参考:
http://www.shido.info/lisp/scheme7_e.html
Function fact that calculates factorials.
(define (fact n)
(if (= n 1)
1
(* n (fact (- n 1)))))
(fact 5) is calculated like as follows:
(fact 5)
⇒ 5 * (fact 4)
⇒ 5 * 4 * (fact 3)
⇒ 5 * 4 * 3 * (fact 2)
⇒ 5 * 4 * 3 * 2 * (fact 1)
⇒ 5 * 4 * 3 * 2 * 1
⇒ 5 * 4 * 3 * 2
⇒ 5 * 4 * 6
⇒ 5 * 24
⇒ 120
(fact 5) calls (fact 4), (fact 4) calls (fact 3), then finally (fact 1) is called. (fact 5), (fact 4) ,.., and (fact 1) are allocated at different memory spaces and(fact i) stays there until (fact (- i 1)) returns a value, which wastes the memory space and takes more calculation time because of the overhead of function call.
However, recursive functions can express repetition in a simple manner. Further as lists are defined recursively, lists and recursive functions fit together. For instance, a function that makes all list items twice is defined like as follows. The function should return an empty list if the argument is an empty list to terminate the calculation.
(define (list*2 ls)
(if (null? ls)
'()
(cons (* 2 (car ls))
(list*2 (cdr ls)))))
3. Tail Recursive
Ordinary recursive function is not efficient because of wasting memory and function call overhead. On the contrary, tail recursive functions include the result as argument and returns it directory when the calculation finishes. Especially, as Scheme specification requires conversion of a tail recursive to a loop, there is no function call overhead.
[code 2] shows a tail recursive version of function fact shown in [code 1].
[code 2] fact-tail, tail recursive version of fact
(define (fact-tail n)
(fact-rec n n)) (define (fact-rec n p)
(if (= n 1)
p
(let ((m (- n 1)))
(fact-rec m (* p m)))))
fact-tail calculates factorial like as follows:
(fact-tail 5)
⇒ (fact-rec 5 5)
⇒ (fact-rec 4 20)
⇒ (fact-rec 3 60)
⇒ (fact-rec 2 120)
⇒ (fact-rec 1 120)
⇒ 120
As fact-rec does not wait the result of other functions, it disappears from the memory space when it finishes. The calculation proceeds by changing argument of fact-rec, which is basically the same as loop. As mentioned previously, as Scheme convert a tail recursive to a loop, Scheme can do repetition without syntax for looping.
4. Named let
The named let is available to express loop. [code 3] shows a function fact-let that calculates factorials using named let. The fact-let uses a named let expression (loop), instead of fact-rec shown in [code 2]. First it initializes parameters (n1, p) with n at the line marked with ; 1. These parameters are updated at the line marked with ; 2 after each cycle: Subtracting n1 by one and multiplying p by (n1-1)
A named let is a conventional way to express loops in Scheme.
[code 3]
(define (fact-let n)
(let loop((n1 n) (p n)) ; 1
(if (= n1 1)
p
(let ((m (- n1 1)))
(loop m (* p m)))))) ; 2
5. letrec
While it is similar to the named let, a name defined by letrec can refer itself in its definition. The letrec syntax is used to define complicated recursive functions. [code 4] shows a letrec version of fact.
[code 4]
(define (fact-letrec n)
(letrec ((iter (lambda (n1 p)
(if (= n1 1)
p
(let ((m (- n1 1)))
(iter m (* p m))))))) ; *
(iter n n)))
As shown at the line of ; *, the local variable iter can refer itself in the definition of iter. Syntax letrec is a conventional way to define local functions.
scheme递归的更多相关文章
- Teach Yourself Scheme in Fixnum Days 6 recursion递归
A procedure body can contain calls to other procedures, not least itself: (define factorial (lambda ...
- Scheme中一些函数在C++里面的实现与吐槽
最终我失败了,这是显而意见,我试图在一个很看重类型是什么的语言中实现无类型操作,事实上,哪怕我实现了基本的cons,car,cdr,list后面的代码也无法写下去.比如说list-n,根据 ...
- 与Scheme共舞
发表在<程序猿>2007年7月刊上.不log上写帖子不用考虑版面限制,所以这里的帖子比发表的啰嗦点.赵健平编辑,Jacky,和刘未鹏都给了我非常多帮助,在这里一并谢了.免费的Scheme实 ...
- 递归转手工栈处理的一般式[C语言]
是任意形式的递归,是化解的一般式. 主题所谓的“递归调用化解为栈处理”,意思是,将递归函数调用化解为“一个由stack_push stack_pop stack_top等函数调用组成的循环式子”.这里 ...
- MIT scheme入门使用
在win7下可安装MIT-GUN scheme, 点开后有两个界面:一个交互式命令行界面:一个Edwin界面. 在命令行界面按Ctrl-G可以开始输入.在Edwin界面,输入完整命令后按Ctrl ...
- scheme Continuation
Continuation Pass Style在函数式编程(FP)中有一种被称为Continuation Passing Style(CPS)的风格.在这种风格的背后所蕴含的思想就是将处理中可变的一部 ...
- 递归——CPS(一)
程序中为什么需要栈stack? 普通的程序中,接触到子程序和函数的概念,很直观地,调用子程序时,会首先停止当前做的事情,转而执行被调用的子程序,等子程序执行完成后,再捡起之前挂起的程序,这有可能会使用 ...
- Scheme实现二叉查找树及基本操作(添加、删除、并、交)
表转化成平衡二叉树 其中有一种分治的思想. (define (list->tree elements) (define (partial-tree elts n) (if (= n 0) (co ...
- Scheme r5rs letrec的用法
说明,这是r5rs的用法. (letrec ((<variable> <init>) ...) <body>) 假设((<variable> <i ...
随机推荐
- git push error: RPC failed; result=56, HTTP code = 0 ,the remote end hung up unexpectedly
git push的时候发生标题上面的错误,不知道怎么解决.搜索了下stackoverflow,上面说是http的postBuffer不够导致的. 要运行以下命令: git config --globa ...
- 匹配“is outside location”
<pre name="code" class="html">is outside location 怎么匹配? . 匹配除换行外的所有单个字符,通常 ...
- Compound class names are not supported. Consider searching for one class name and filtering the results
原文地址:http://stackoverflow.com/questions/20361643/compound-class-names-are-not-supported-consider-sea ...
- 什么是内存泄漏?(What is a memory leak?)
程序中的内存泄漏是怎么回事呢? 我们写过很多带有关键词free()的程序.比如我在这篇博文关于链表的一些重要操作(Important operations on a Linked List)中删除整个 ...
- 精确覆盖DLX算法模板
代码 struct DLX { int n,id; int L[maxn],R[maxn],U[maxn],D[maxn]; ]; ) //传列长 { n=nn; ;i<=n;i++) U[i] ...
- UIScrollView入门与框架设计
一.概述 1.UIScrollView的contentSize, contentOffSet, contentInsets的作用和使用. 2.UIScrollView的一整个滚动过程的生命周期(开始滚 ...
- 飘逸的python - 性能调优利器profile及其意义
VIM 的作者Bram Moolenaar在一篇叫高效文本编辑器的7个习惯的ppt中有这么一段话. Three basic steps 1. Detect inefficiency 2. ...
- Smart ——jiaoyou模板
<!--{foreach $vip_data as $key=>$volist}--> <!--{if $key==0 ||$key==1||$key==5||$key= ...
- Unity Navigation面板了解
上次讲解了下Navigation的简单使用, 这次来看看Navigation面板的一些参数 NavigationStatic 勾选后表示该对象参与导航网格的烘培. OffMeshLink Genera ...
- 苹果拒绝App内部使用版本检测功能
10.6 - Apple and our customers place a high value on simple, refined, creative, well thought through ...