Я конвертирую некоторый код Scheme в Clojure.В оригинале используется схема диспетчеризации, которая очень похожа на мультиметоды, но с перевернутым подходом к сопоставимым предикатам.Например, есть универсальная функция «назначить операции».Точные детали реализации в данный момент не слишком важны, но обратите внимание, что он может принимать список аргументов-предикатов.
(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?)
Позже, когда вызывается универсальная функция "слияние", каждый обработчик спрашивается, работает ли он с операндами.
Как я понимаю, мультиметоды, функция диспетчеризации определеначерез набор реализаций, с отправкой в конкретный метод, основанный на возвращаемом значении dispatch-fn.На приведенной выше схеме новые функции операции присваивания могут произвольно определять предикаты.
Какой будет эквивалентная идиоматическая конструкция в Clojure?
РЕДАКТИРОВАТЬ: Код выше взят из "Искусство пропагандиста" , Алексея Радула и Джеральда Суссмана.