SICP 图片语言练习 Lambda 论证

SICP The Picture Language Exercise Lambda Argument

(define (segments->painter segment-list)
  (lambda (frame)
    (for-each
      (lambda (segment)
        (draw-line
          ((frame-coord-map frame)
           (start-segment segment))
          ((frame-coord-map frame)
           (end-segment segment))))
      segment-list)))

有些人之前已经看过这个 sicp 示例,但对于初学者来说,有一个简短的解释:segments->painter 过程从段列表中获取参数,该列表的值是由向量组成的段。 for-each 过程就像 map 一样,但 returns 是一个值列表,它执行打印等操作,或者在这段代码中画线。 frame-coord-map 根据单位正方形框架缩放框架。我在这段代码中不明白的是第一个 lambda 函数从哪里获取它的参数(框架)。

让我们看一个更简单的例子:

(define (adder x)
  (lambda (y)
    (+ x y))

类似的问题是,“如果只用 x 就可以调用 addery 从哪里来?”正如评论中所讨论的,它来自调用 lambda adder returns 的人。你可以写:

(define plus5 (adder 5))
(plus5 8) ; 13
(plus5 1) ; 6

在你调用adder的时候,没有y。在接下来的调用中,y 是 8,之后是 1.

同样在您的实际代码中,没有 frame 直到有人调用返回的 lambda。

这里是currying的案例。

在你的代码中

(define (segments->painter segment-list)
  (lambda (frame)
     ...))

当你调用segments->painter时,scheme会return一个类型的对象,让我们调用figure。当您在此对象上应用图形框架时,scheme 将能够绘制您的对象。

(define obj1 (segments->painter seg1))

obj1 是类型为 figure 的对象,并且此对象能够接收帧。它在接收到一帧时只能执行一个操作,即在该帧中绘制:(obj1 frame1)(obj1 frame2) 等是您可以对该对象执行的操作。

在将图形数据应用于某个对象之前,谈论该对象确实有意义,但谈论该对象的真实表示是没有意义的。在您的情况下,该对象可以执行一个操作:绘制。

在为 figure 对象调用构造函数和绘制对象之间,您可以进行一些(静态)预处理,这样在您调用绘图方法的那一刻,您已经预先计算了一些东西。

这就是类型在编程语言中的实现方式。 Peter Henderson 的这种语言是对类型和组合器的首次介绍。这将在第 4 章中进一步发展,其中解释器使用一些预先计算的数据来执行(它将列表输入格式转换为内部格式)。