> (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. C#之转换两个不同类型但是成员相同的对象

    /// <summary> /// 转换两个不同类型但是成员相同的对象 /// </summary> /// <typeparam name="T"& ...

  2. Pycharm数据库连接错误

    简单地总结就一句话: Python2的mysql库为:mysqldb,而Python3的为:pymysql. 当我们使用Pycharm开发项目时,首先需要下载安装相对应的数据库,以及在项目根目录下的s ...

  3. Field的getModifiers()方法返回int类型值表示该字段的修饰符

    其中,该修饰符是java.lang.reflect.Modifier的静态属性. 对应表如下: PUBLIC: 1PRIVATE: 2PROTECTED: 4STATIC: 8FINAL: 16SYN ...

  4. Redis数据类型--string

    在Redis中支持丰富的数据类型的存储系统,包括:字符串(string),散列(hashes),列表(lists),集合(sets),有序集合(sorted sets),与范围查询,bitmaps,h ...

  5. HttpClient入门一

    HttpClient是一个实现了Http协议的功能强大的编程工具包. 要使用HttpClient,通常需要以下几部: 1.常见一个HttpClient实例 2.创建一个get或者post方法 3.告诉 ...

  6. 用DotTrace 来分析.NET-Core程序

    1. 前言   看园子里面讲dotTrace 的文章不多,最近也有这方面的需要,于是去搜索了一下,.NET 性能分析方面的工具.目的呢,主要是想发现我的代码中,哪些代码占用了最多时间,来进行优化.主要 ...

  7. 2015 多校联赛 ——HDU5373(模拟)

    Problem Description In this problem, we should solve an interesting game. At first, we have an integ ...

  8. SPFA小总结

    关于spfa 知识点 原始版 ---裸 应用: 一.判负环 两种方法 1.跑单源点bfs,如果某一个点入队了n-1次,存在 2.对于每个点dfs,如果此源点反被其他点更新,存在 证明:点i作为源点,d ...

  9. mycat 1.6 简单的操作实例

    环境: centos7.4 + mysql5.7.20 + mycat1.6单台主机上安装了5台mysql_5.7.20 实例(3306,3307,3308,3309,3310)3306为独立实例 ( ...

  10. Python使用wmi获取Windows相关信息

    在使用Python获取Windows系统上的相关的信息可以使用WMI接口来获取, 什么是wmi? WMI是一项核心的Windows管理技术,WMI作为一种规范和基础结构,通过它可以访问.配置.管理和监 ...