我正在从编程入门课程中看一些额外的练习,这是关于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))
))))
我将调用定义为将可选参数应用于对象方法的函数。 (我对这里的语法并不感到厌倦,但这是给定的,我认为我理解的意思是:"首先将方法应用于对象,如果你有参数,也将它们放入&#34 ;)
(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 '.'
错误。)
有人可以澄清在这种情况下,使用可选参数的输入是如何实际工作的吗?
答案 0 :(得分:2)
(-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)
的返回值也是(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)
相同。
答案 1 :(得分:1)
您应该知道的第一件事是点符号将零点或更多项绑定到点后面的名称作为列表。
(define (exmaple a b .c) c)
(example 1 2 3 4 5) --> (3 4 5)
其次定义了不是' textual,除非你使用文字。当您将x定义为y时,y在与x关联之前进行求值。 C1不是'(-circle- 3)
它是使用参数3评估-circle-的结果,它是一个环境中的函数(lambda (method-name) ...)
,其中名为radius的变量是3。
所以(call c1 'area)
做的是评估半径为3的((lambda (method-name) ...) 'area)
。它返回(lambda () (* pi r r))
,其中radius为3. Apply然后将该函数应用于空列表(由于函数没有正式参数而适合),返回结果为9 * pi