named let 递归和闭包的利器
2024-08-26 21:09:34
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))
最新文章
- 我的基于asp.net mvc5 +mysql+dapper+easyui 的Web开发框架(1)数据库访问(0)
- 如何实时查看linux下的日志
- 亿级Web系统搭建——单机到分布式集群
- edittext 监听内容变化
- html之给文本框设置宽度和高度/input的无边框效果
- Hadoop系统架构
- Call to undefined function curl_init()解决方法
- Game of Life 解答
- HTML5实现涂鸦板
- js获取浏览器宽高
- Vue.js 入门
- Ant的使用
- Java不走弯路教程(4.Client-Server模式(1)-Server)
- Gradle初探
- Understanding HBase and BigTable
- apk的api级别不要低于26
- Async/Await是这样简化JavaScript代码的
- Python3 tkinter基础 Entry show textvariable 密码输入框
- 回归——继续我的ACM之路!!
- 匿名函数、闭包、lambda表达式、Block