Scheme - 方法调用中可选参数的语法

Scheme - Syntax of optional arguments in a method call

我正在看编程入门课程的一些额外练习,这是来自 OOP with Scheme 的部分。

我将 -circle- 定义为具有参数半径的对象。 另外,我将区域定义为 -circle- 的方法。

(define -circle-
  (lambda (r)
    (define area (lambda () (* pi r r)))
    (lambda (method-name)
      (cond
        ((eq? method-name 'area) area)
        (else (error '-circle- "Method not found: ~s" method-name))
        ))))

我将调用定义为将可选参数应用于对象方法的函数。 (我对这里的语法并不满意,但这是给定的,我想我理解的意思是:"first apply the method to the object, if you have arguments, put them in too")。

(define call
  (lambda (obj method-name . args)
    (apply (obj method-name) args)))

测试示例(在 DrRacket/Pretty Big 中完美运行)是:

(define c1 (-circle- 3))
(call c1 'area)

但在我看来,这个关闭会带来:

(call -circle- 3 'area)

而不是:

(call -circle- 'area . 3)

(这反过来会导致 illegal use of '.' 错误)。

有人可以阐明在这种情况下带有可选参数的输入实际上是如何工作的吗?

(-circle- 3)的结果是这样的:

(lambda (method-name)
  (cond ((eq? method-name 'area) area)
        (else (error '-circle- "Method not found: ~s" method-name))))

area 设置为 (lambda () (* pi 3 3))。这意味着 ((-circle- 3) 'area) 的 return 值也是 (lambda () (* pi 3 3)).

调用 (call (-circle- 3) 'area)(apply ((-circle- 3) 'area) '()) 具有相同的效果(因为其余参数 args 为空),这与评估 (((-circle- 3) 'area)) 相同,我们知道它与 ((lambda () (* pi 3 3))) 相同,后者的计算结果为 (* pi 3 3).

注:(call (-circle- 3) 'area)(call -circle- 3 'area)不同

您应该知道的第一件事是点符号将零个或多个项目绑定到点后面的名称作为列表。

(define (exmaple a b .c) c)
(example 1 2 3 4 5) --> (3 4 5)

其次定义不是文本,除非您使用文字。当您将 x 定义为 y 时,y 在与 x 关联之前先求值。 C1 不是 '(-circle- 3),它是使用参数 3 评估 -circle- 的结果,它是变量 radius 为 3 的环境中的函数 (lambda (method-name) ...)

所以 (call c1 'area) 所做的是评估 ((lambda (method-name) ...) 'area) 其中半径为三。它 returns (lambda () (* pi r r)) 其中半径为 3。 Apply 然后将该函数应用于空列表(这是合适的,因为该函数没有正式参数)returns 9*pi[ 的结果=16=]