我正在将一些 Scheme 代码转换为 Clojure。最初使用的调度模式与多方法非常相似,但对匹配谓词采用了倒置的方法。例如,有一个通用函数“assign-operations”。目前,精确的实现细节并不太重要,但请注意它可以采用参数谓词列表。
(define (assign-operation operator handler . argument-predicates)
(let ((record
(let ((record (get-operator-record operator))
(arity (length argument-predicates)))
(if record
(begin
(if (not (fix:= arity (operator-record-arity record)))
(error "Incorrect operator arity:" operator))
record)
(let ((record (make-operator-record arity)))
(hash-table/put! *generic-operator-table* operator record)
record)))))
(set-operator-record-tree! record
(bind-in-tree argument-predicates
handler
(operator-record-tree record)))))
分派的函数提供这些谓词,函数的元数中的每个参数一个。
(assign-operation 'merge
(lambda (content increment) content)
any? nothing?)
(assign-operation 'merge
(lambda (content increment) increment)
nothing? any?)
(assign-operation 'merge
(lambda (content increment)
(let ((new-range (intersect-intervals content increment)))
(cond ((interval-equal? new-range content) content)
((interval-equal? new-range increment) increment)
((empty-interval? new-range) the-contradiction)
(else new-range))))
interval? interval?)
稍后,当调用通用函数“merge”时,会询问每个处理程序是否适用于操作数。
据我了解多方法,调度函数是在一组实现中定义的,根据 dispatch-fn 的返回值调度到特定方法。在上面的 Scheme 中,新的赋值操作函数可以任意定义谓词。
Clojure 中的等价的惯用构造是什么?
编辑:上面的代码来自Alexey Radul 和 Gerald Sussman的“传播者的艺术” 。