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 ...
随机推荐
- Android得到控件在屏幕中的坐标
getLocationOnScreen ,计算该视图在全局坐标系中的x,y值,(注意这个值是要从屏幕顶端算起,也就是索包括了通知栏的高度)//获取在当前屏幕内的绝对坐标 getLocationInWi ...
- linux环境c++开发:ubuntu12.04使用llvm3.4.2
什么是 clang/llvm/libc++[1] clang 是最近几年(在大财主苹果的支持下)发展得非常好的 C 家族语言 (包括C/C++/Obj-C/Obj-C++) 编译器前端,所谓前端,就是 ...
- 《数据通信与网络》笔记--SSL/TLS
上次简单地介绍了IP层的安全,今天来介绍下在传输层提供安全性最主要的2个协议:安全套接字层(SSL)协议和传输 层安全(TLS)协议.TLS实际上就是SSL的IETF版本. 1.SSL服务 设计安全套 ...
- Linux2.6内核 -- 结构的初始化
Linux 内核中用到了大量的结构体,在编码规范中也给出了结构体初始化的规则,这篇文章中有对其的解释:http://blog.csdn.net/dlutbrucezhang/article ...
- 多个文件目录下Makefile的写法
1.前言 目前从事于linux下程序开发,涉及到多个文件,多个目录,这时候编译文件的任务量比较大,需要写Makefile.关于Makefile的详细内容可以参考网上流传非常广泛的<跟我一起写Ma ...
- Linux 通过HTTP进行域名更新
一.3322动态域名更新接口 接口地址 API URL http://members.3322.net/dyndns/update HTTP请求 GET /dyndns/update?hostname ...
- qt model/view 架构基础介绍之QTableWidget
# -*- coding: utf-8 -*- # python:2.x #说明:QTreeWidget用于展示树型结构,也就是层次结构同前面说的 QListWidget 类似,这个类需要同另外一个辅 ...
- java技术学习网址收藏
Bootstrap:http://www.runoob.com/bootstrap/bootstrap-intro.html AngularJS : http://www.runoob.com/ang ...
- spring容器IOC原理解析
原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean ...
- 关于使用STL常见的两个bug
1.bug 1 class CTest { public : vector<int> getVector() const //需要写成引用形式,不然下面begin.end调用会以拷贝形式调 ...