谁能简单地向我解释一下消息传递是如何在方案中实现的?我认为我对消息传递的整个概念不太了解。
2 回答
闭包上下文中的消息传递
下面的示例定义了一个实现简单计算器的闭包。该函数make-calculator
类似于面向对象的语言调用构造函数。区别在于:make-calculator
返回一个函数,而构造函数返回对象值。在面向对象的语言中,对象值是一等值。Scheme 没有这样的值。对象第一类值提供访问对象成员变量和对象方法的功能。在 Scheme 中,这个功能必须通过调度函数的定义来模拟。make-calculator
返回这样的函数。make-calculator
定义的主体
- 两个变量
a
和b
(成员变量) - 两个变异函数
set-a!
和set-b!
(访问器) - 四个评估函数
addition
,subtraction
,multiplication
和division
(方法)
上面的定义是闭包的本地定义make-calculator
。在面向对象的语言中,它们被称为私有的。分派函数使函数公开并保持变量私有。这是可行的,因为调度函数可以访问make-calculator
闭包的本地范围。dispatch 函数接受消息并返回匹配的函数。这会将本地函数暴露给调度函数的调用者。
(define (make-calculator)
(define a)
(define b)
(define (set-a! value)
(set! a value))
(define (set-b! value)
(set! b value))
(define (addition)
(+ a b))
(define (subtraction)
(- a b))
(define (multiplication)
(* a b))
(define (division)
(/ a b))
(lambda (message)
(case message
((set-a!) set-a!)
((set-b!) set-b!)
((addition) addition)
((subtraction) subtraction)
((multiplication) multiplication)
((division) division))))
首先必须调用构造函数来创建一个“对象”。calc
是 dispatch 函数,它接受不同的消息,这些消息只是符号。
(define calc (make-calculator))
发送消息意味着使用符号参数调用调度函数。下面将消息发送set-a!
到calc
,它返回本地函数的值set-a!
。在这种情况下,消息的名称和本地函数的名称是相同的。这有助于避免混淆,但这不是必需的。
(calc 'set-a!) ;; => #<procedure set-a!>
因为calc
返回一个函数,所以需要一个额外的应用程序来调用访问器。以下设置a
为 3 和b
5。
((calc 'set-a!) 3)
((calc 'set-b!) 5)
现在我们可以计算:
((calc 'addition)) ;; => 8
((calc 'subtraction)) ;; => -2
((calc 'multiplication)) ;; => 15
((calc 'division)) ;; => 3/15
代码在Chez Scheme中以这种方式工作。