Scheme中两个函数之间的区别是什么,一个定义如下 -
(define doSomething
(lambda (x)
(let (f (100))
(f x))))
Run Code Online (Sandbox Code Playgroud)
而另一个是这样的? -
(define doSomething
(let (f (100))
(lambda (x)
(f x))))
Run Code Online (Sandbox Code Playgroud)
换句话说,如果它在它lambda
之前let
或之后有什么关系呢?
您的代码将无法运行.:-)
我会认为你的意思是:
(lambda (x)
(let ((f 100))
(+ f x)))
Run Code Online (Sandbox Code Playgroud)
和
(let ((f 100))
(lambda (x)
(+ f x)))
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,您将获得传入的参数加100.
然而,主要区别(忽略关于如何let
只是语法糖的技术性lambda
)是在第二个版本中,f
是一个自由变量.说我们这样做:
(let ((f 100))
(list (lambda (x)
(+ f x))
(lambda (x)
(set! f x))))
Run Code Online (Sandbox Code Playgroud)
这将返回一个包含两个lambdas的列表:第一个与之前的一样,第二个允许您更改值f
.两个lambdas访问相同f
,因此运行setter 将影响以后对第一个lambda的调用.
克里斯指出,代码不会运行.所以我将使用一个新的例子来解释let
了lambda
成语.
当您使用以下内容包围lambda
表单时let
:
(let ((x 0))
(lambda ()
; body
))
Run Code Online (Sandbox Code Playgroud)
身体内部的代码lambda
能够访问(包括修改)x
,甚至在let
结束后返回新函数.这是创建"闭包"的一个例子,起初很难理解.
从本质上讲,这意味着您可以创建一种具有"内部状态"的功能.您可以使用它来执行诸如制作"累加器生成器"之类的操作,或者创建计算它们被调用次数的函数,甚至模拟"对象"(内部状态+方法).这是一些人为的例子:
一个double
计算被调用次数的函数:
(define double
(let ((count 0)) ; closed over variable
(lambda (x)
(if (eq? x 'count)
count
(begin
(set! count (+ count 1)) ; incr the count variable introduced by let
(+ x x))))))
> (double 1)
2
> (double 1)
2
> (double 1)
2
> (double 'count) ; ask the double function how many times it's been called
3
>
Run Code Online (Sandbox Code Playgroud)
这个例子非常礼貌Paul Graham(http://www.paulgraham.com/accgen.html)
(define make-accumulator
(lambda ()
(let ((x 0))
(lambda (i)
(set! x (+ x i)) ; incr x by i
x))))
> (define acc (make-accumulator))
> (acc 1)
1
> (acc 1)
2
> (acc 1)
3
> (acc 1)
4
>
Run Code Online (Sandbox Code Playgroud)
每次acc
调用1
它返回的值都不同.
有关"对象"的示例搜索"对象和闭包"或只是阅读SICP的相关部分:http://mitpress.mit.edu/sicp/full-text/book/book-ZH-20.html#%_sec_3 0.1
归档时间: |
|
查看次数: |
1396 次 |
最近记录: |