> (define (f x) x)
> (define (g x) (let rec((x x)) x))
> (define a '(1 2 3)) > (f a)
( )
> (eq? a (f a))
#t
> (eq? a (g a))
#t > (define b (g a))
> (set-car! b )
> a
( )
>

可见,g函数的定义中,named let并未深拷贝x的值,它只是建立传入参数的引用而已.

那这也说明,如果一个函数所有参数在递归过程中都会发生改变,那么一般没必要用named let.

又如:

;切割named let版 (   )  -> ( )
(define (tail x n)
(let recur ((x x)(n n))
(if (null? x)
'()
(if (> n )
(recur (cdr x) (- n ))
(cons (car x) (recur (cdr x) (- n ))))))) ;切割原始版
(define (tail x n)
(if (null? x)
'()
(if (> n )
(tail (cdr x) (- n ))
(cons (car x) (tail (cdr x) (- n ))))))

原始版就是更好的.

但是,对于递归过程中函数所有参数都在变化的情形,有两种情况例外,仍然需要named let:

(1)函数要求返回递归过程中的某些变量的最终状态.例如求一个list的元素个数的函数定义:

(define (len x)
(let recur ((x x)(y ))
(if (null? x)
y
(recur (cdr x) (+ y )))))

由于需要一个变量来记录(cdr x)的次数,因此在内嵌函数recur中增加一个参数y来实现是非常合适的.

(2)处理不定参数的情形.这个可以用map来作非常好的说明:

(define (imap f x . y)
(if (null? y)
(let recur ((x x))
(if (null? x)
'()
(cons (f (car x)) (recur (cdr x)))))
(let recur ((x x) (y y))
(if (null? x)
'()
(cons (apply f (car x) (imap car y)) (recur (cdr x) (imap cdr y)))))))

显然,结合条件判断,named let能够将复杂情形转化为简单情形.思路是:

如果y是空表,那么imap等于一个只有1个参数recur函数.否则就等于2个参数的recur函数.而后者的参数传递过程中,我们又需要用到1个参数的情形:

(imap car y)
(imap cdr y)

这真是非常精妙的.

不应滥用named let的更多相关文章

  1. LINQ使用细节之.AsEnumerable()和.ToList()的区别

    先看看下面的代码,用了 .AsEnumerable(): 1 var query = (from a in db.Table2 where a = SomeCondition3 select a.So ...

  2. linux面试题

    一.填空题: 1. 在Linux系统中,以 文件 方式访问设备 . 2. Linux内核引导时,从文件 /etc/fstab 中读取uu要加载的文件系统. 3. Linux文件系统中每个文件用 i节点 ...

  3. Linux笔试常见填空题

    一.填空题: 在Linux系统中,以 文件 方式访问设备 . Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统. Linux文件系统中每个文件用 i节点 来标识. 全部磁盘块 ...

  4. Linux面试题汇总答案

    转自:小女生的Linux技术~~~Linux面试题汇总答案~~ 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的 ...

  5. linux 笔试题

    一.填空题: 1. 在Linux系统中,以 文件 方式访问设备 . 2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统. 3. Linux文件系统中每个文件用 i节点 来 ...

  6. Linux 面试题总结

    一. 填空题1. 在Linux系统中,以 (文件) 方式访问设备 .2. Linux内核引导时,从文件 (/etc/fstab) 中读取要加载的文件系统.3. Linux文件系统中每个文件用 (索引节 ...

  7. linux常见问题集锦-1

    http://www.cnblogs.com/itech/archive/2011/02/12/1952857.html 感谢作者分享 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 . ...

  8. linux常见问题集锦

    本文转自 http://bbs.chinaunix.net/thread-3668921-1-1.html,在此感谢作者分享 一.填空题: 1. 在Linux系统中,以 文件 方式访问设备 . 2. ...

  9. linux面试题及答案

    http://www.cnblogs.com/itech/archive/2011/02/12/1952857.html 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linu ...

随机推荐

  1. [SDOI2016]硬币游戏

    题目描述 Alice 和 Bob 现在在玩的游戏,主角是依次编号为 1 到 n 的 n 枚硬币.每一枚硬币都有两面,我们分别称之为正面和反面.一开始的时候,有些硬币是正面向上的,有些是反面朝上的.Al ...

  2. 洛谷P1446 [HNOI2008]Cards

    置换群+dp #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring& ...

  3. Codeforces April Fools Contest 2017

    都是神题,我一题都不会,全程听学长题解打代码,我代码巨丑就不贴了 题解见巨神博客 假装自己没有做过这套

  4. bzoj 4567: [Scoi2016]背单词

    Description Lweb 面对如山的英语单词,陷入了深深的沉思,"我怎么样才能快点学完,然后去玩三国杀呢?".这时候睿智 的凤老师从远处飘来,他送给了 Lweb 一本计划册 ...

  5. hdu 2865 Polya计数+(矩阵 or 找规律 求C)

    Birthday Toy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  6. [bzoj4820][Sdoi2017]硬币游戏

    来自FallDream的博客,未经允许,请勿转载,谢谢. 周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利.大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了 ...

  7. spring boot新建项目问题总结

    1.启动报:Unregistering JMX-exposed beans on shutdown 原因:以来的Tomcat没有启动 解决办法:在pom.xml加入依赖 <dependency& ...

  8. C语言程序设计第一次作业(2017.10.10完成)

    一:程序框图以及正确运行结果: (1)给出圆半径,得出圆面积: ①程序框图如下: ②测试图如下: 经过测试 ,输入半径2能得出正确结果.多次测试,输入不同值,均得出正确结果,证明稳定性. ③实验分析: ...

  9. WEB中间件--Jboss未授权访问,

    1,Jboss未授权访问部署木马 发现存在Jboss默认页面,点进控制页 点击 Jboss.deployment 进入应用部署页面 也可以直接输入此URL进入 http://www.ctfswiki. ...

  10. Oracle的dual

    1.dual 确实是一张表.是一张只有一个字段,一行记录的表. 2.习惯上,我们称之为'伪表'.因为他不存储主题数据.3.他的存在,是为了操作上的方便.因为select 都是要有特定对象的.但如果我们 ...