named let和递归,闭包联系十分密切.而且还是提高性能的重要手段.先来看一个make-list函数的模拟,最原始的写法大概是:

(define (imake-list n member)
(if (= n)
(cons member '())
(cons member (imake-list (- n ) member))))

这种写法的毛病在于:

1.递归过程中,member变量可能需要在全局作用域中查找,比局部作用域查找要慢.

2.member是一个固定的参数,然而递归过程在不断重复将它传入imake-list.

这个时候你需要 named let,完美解决这2个问题:

(define (imake-list n member)
(let recur ((n n))
(if (= n)
(cons member '())
(cons member (recur (- n )))))) (imake-list "a")

具体过程:

1.let创建了一个内部函数recur.它接受一个参数,返回一个列表.

2.imake-list的n传递给了recur的n.而后者是在局部作用域.

3.递归过程转移到recur中进行,固定参数member成了它的自由变量.避免了重复传入的问题.

似乎迭代和递归会很频繁地用到这种技巧,例如很基本的函数map的模拟,也可以分为2个版本:

;原始低效版
(define (imap f x . y)
(if (null? y)
(if (null? x)
'()
(cons (f (car x)) (imap f (cdr x))))
(if (null? x)
'()
(cons (apply f (car x) (imap car y)) (apply imap f (cdr x) (imap cdr y)))))) ;named let高效版
(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))))))) (map + '(1 2 3) '( ) '(1 2 3))
(imap + '(1 2 3) '( ) '(1 2 3))

named let 递归和闭包的利器的更多相关文章

  1. 浅谈javascript中的递归和闭包

    递归和闭包作为js中很重要的一环,几乎在前端的面试中都会涉及,特别闭包.今天前端组的组长冷不丁的问了我一下,粗略的回答了一下,感觉不太满足,于是重新学习了一下,写下本篇. 在说这个两个概念之前,我们先 ...

  2. 四、golang内置函数、递归、闭包、数组切片和map

    一.总体内容 1.内置函数.递归函数.闭包 2.数组和切片 3.map数据结构 4.package介绍 一.内置函数 注意:值类型用new来分配内存,引用类型用make来分配内存 1.close:主要 ...

  3. php闭包实现函数的自调用,也是递归

    php的闭包可能不常用,但是在某些场合之下还是可以考虑用php的闭包来实现某些功能的,比如递归,这里讲一下用php的闭包实现递归 //php闭包实现函数的自调用,也就是实现递归 function cl ...

  4. PHP闭包实现函数的自调用实现递归

    根据pathinfo访问对应得controller,如ip:port/home/index/index则会访问home目录下的IndexController的index方法:如果不指定pathinfo ...

  5. 递归转手工栈处理的一般式[C语言]

    是任意形式的递归,是化解的一般式. 主题所谓的“递归调用化解为栈处理”,意思是,将递归函数调用化解为“一个由stack_push stack_pop stack_top等函数调用组成的循环式子”.这里 ...

  6. 简学Python第三章__函数式编程、递归、内置函数

    #cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...

  7. 第四章 函数(JavaScript:语言精粹)

    函数包含一组语句,用来指定对象的行为,其代码可以用来重复使用.   一般来说,编程就是将一组需求分解成一组函数和数据结构的技能.   概览:函数对象 | 函数字面量 | 调用 | 方法调用模式 | 函 ...

  8. 简述 Ruby 与 DSL 在 iOS 开发中的运用

    阅读本文不需要预先掌握 Ruby 与 DSL 相关的知识 何为 DSL DSL(Domain Specific Language) 翻译成中文就是:"领域特定语言".首先,从定义就 ...

  9. JavaScript高级 函数表达式 《JavaScript高级程序设计(第三版)》

    函数表达式的特征 使用函数实现递归 使用闭包定义私有变量 前面我们说到定义函数有两种方式:函数声明.函数表达式. 两者的区别在于函数声明提升,前者在执行之前的上下文环境中直接被赋值,而后者不会. 一. ...

随机推荐

  1. svg param.js的大bug

    在svg文件里定义控件,带参数,然后引用. 如果是 text 且没有为其它添加默认值,那么会报错. 即, <svg width="200" height="200& ...

  2. elasticsearch logstash jdbc 配置 增量更新

    环境前提: centos 6.5 x64 jdk 1.8 elasticsearch 6.1.4 logstash 6.1.4 kibana 6.1.4 mysql 5.x 保证上面软件已经安装,并且 ...

  3. postman学习笔记(一)——最简单的postman入门

    昨天开始正式接触postman的操作,最简单的操作是根据接口文档一个个测试接口. 例如: 测试环境地址:http://111.2.198.4(项目组自己的测试环境,要测试的项目组肯定会给你的) //以 ...

  4. HashMap 你真的了解吗?

    HashMap深入解析及详细介绍 一. hashmap简介 HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特 ...

  5. git中的merge与rebase

    之前一直对git的merge与rebase很困惑,而且一般也只使用merge而不是使用rebase.今天受高人指点理清了两者的区别. 首先对于两者而言,他们的结果是一样的,差异在于合并的方式(产生的结 ...

  6. PostgreSQL的insert注入

    写这篇文是在昨夜的ctf中遇到的. ctf地址:bloody-feedback.quals.2017.volgactf.ru email存在注入,在ctf中发现注入就很好办了,只要找到能绕过的方法就行 ...

  7. 系统引导修复 ---- Windows 和 Ubuntu

    Windows: 1.准备windows相应镜像盘,u盘启动该系统 (以下均为windows10安装界面) 2.进入安装界面<语言,时间,键盘格式>,点击"下一步" 3 ...

  8. [HNOI2009]图的同构

    Description 求两两互不同构的含n个点的简单图有多少种. 简单图是关联一对顶点的无向边不多于一条的不含自环的图. a图与b图被认为是同构的是指a图的顶点经过一定的重新标号以后,a图的顶点集和 ...

  9. [ZJOI2006]物流运输 SPFA+DP

    题目描述 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟踪. ...

  10. NTT+多项式求逆+多项式开方(BZOJ3625)

    定义多项式$h(x)$的每一项系数$h_i$,为i在c[1]~c[n]中的出现次数. 定义多项式$f(x)$的每一项系数$f_i$,为权值为i的方案数. 通过简单的分析我们可以发现:$f(x)=\fr ...