let over lambda

By guenchi at 置顶 • 0人收藏 • 220人看过
> (define f
    (lambda (x)
      (define y 0)
      (set! y (+ x y))
      y))
> (f 1)
1
> (f 2)
2
> (f 3)
3
> (f 4)
4
> (define g
    (let ((y 0))
      (lambda (x)
        (set! y (+ x y))
        y)))
> (g 1)
1
> (g 2)
3
> (g 3)
6
> (g 4)
10


2 个回复 | 最后更新于 置顶
置顶   #1

拿 chez-scheme 的 expand 展开看看。

(expand '(define f (lambda (x) (define y 0) (set! y (+ x y)) y)))

展开后的重命名过于影响可读性,改下名字,就得到:

(begin 
  (set! f 
    (lambda {x} 
       (letrec* ([{y} 0]) 
          (set! {y} (+ {x} {y})
          {y})))

每一次调用过程 f, 就相当于新创建了一个变量 y,且初始值为 0,自然传递给 f 什么值就输出什么值。

第二段代码中,y  在 f 所绑定的过程中属于自由变量,y 被修改之后会保持修改得到的值。

这里歪个楼,define 经过 expand 之后就变成了 set!,这说明 chez-scheme 中的 define 其实就是 set! 吗?

第二段其实也可以也可以写成:

(define f 
   ((lambda (y)
       (lambda (x)
          (set! y (+ x y))
          y)) 1))

f 所绑定的其实是将 1 应用于形参名为 y 的匿名过程后所返回的过程。这里问个问题,y 所绑定的值之所以还在是否因为以 x 作为形参名的匿名函数中存在对变量 y 的引用?

置顶   #2
> (define foo
    (lambda (n)
      (let ((x n))
        (lambda (i)
          (+ x i)))))
> (define acc (foo 3))
> (acc 1)
4
> (acc 10)
13
> (acc 0)
3
>


登录后方可回帖

登 录
信息栏

Scheme中文社区

推荐实现 ChezScheme / r6rs / r7rs large
theschemer.org
Q群: 724577239

精华导览

社区项目

包管理器:Raven
HTTP服务器:Igropyr (希腊火)
官方插件:vscode-chez

社区目标:

完善足以使Scheme工程化和商业化的库,特别是开发极致速度的Web服务器和ANN模块。

一直以来Scheme缺少一个活跃的中文社区,同时中文资料的稀少,导致大多数因为黑客与画家和SICP而接触Scheme的朋友,在学完SICP后无事可做,不能将Scheme转换为实际的生产力。最后渐渐的放弃。
同时Chicken等实现,却因效率问题无法与其他语言竞争。本社区只有一个目的,传播Scheme的文明之火,在最快的编译器实现上,集众人之力发展出足够与其他语言竞争的社区和库。


友情链接:

Clojure 中文论坛
函数式·China


Loading...