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 ...
随机推荐
- linux系统下svn服务器操作命令
linux系统下svn服务器操作命令 .输出指定文件或URL的内容. svncat 目标[@版本]…如果指定了版本,将从指定的版本开始查找. svncat -r PREV filename > ...
- iostat 离线安装
由于lucene需要一定的io读写顾安装iostat来对磁盘io进行监控 iostat 属于sysstat下的功能 git路径如下:https://github.com/sysstat/sysstat ...
- 文本去重之SimHash算法
文本去重之SimHash算法 - pathenon的个人页面 - 开源中国社区 文本去重之SimHash算法
- EditText 文本内容输入限制
实现InputFilter过滤器,需要覆盖一个叫filter的方法. public abstract CharSequence filter ( CharSequence source, int st ...
- 【剑指offer】替换字符串中的空格
转载请注明出处:http://blog.csdn.net/ns_code/article/details/25002199 剑指offer上的第四道题目,在九度OJ上測试通过,但还是有些问题.由于是用 ...
- 开源 免费 java CMS - FreeCMS2.0 会员我的评论
项目地址:http://www.freeteam.cn/ 我的评论 从左側管理菜单点击我的评论进入. 在这里能够查看当前登录会员的全部评论记录. 删除评论 选择评论然后点击删除button能够完毕删除 ...
- Android应用程序资源的编译和打包过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8744683 我们知道,在一个APK文件中,除了 ...
- Android内存泄漏监测(MAT)及解决办法
http://ttlnews.blogspot.com/2010/01/attacking-memory-problems-on-android.html 这篇文章是2010年1月份写的,其中有些已经 ...
- 使用INTERVAL YEAR TO MONTH类型
Oracle Database 9i数据库引入了一种新特性,可以用来存储时间间隔.时间间隔的例子包括: ● 1年零3个月 ● 25个月 ● -3天5小时16分 ● 1天7小时 ● -56小时 注意: ...
- js 随手记
var name = 'frog' function hello(){ alert(name); // undefined var name = 'bbc'; } 在javascript中,函数是可以 ...