いくつかの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)))))
ディスパッチされた関数は、関数のアリティの引数ごとに1つずつ、これらの述語を提供します。
(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の戻り値に基づいて特定のメソッドにディスパッチされます。上記のスキームでは、新しい割り当て操作関数で述語を任意に定義できます。
Clojureの同等の慣用的な構成は何でしょうか?
編集:上記のコードは、AlexeyRadulとGeraldSussmanによる「TheArtofthePropagator 」からのものです。