Scheme -> Clojure: мультиметоды с предикатами в методах?

Я преобразовываю некоторый код 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. В приведенной выше схеме новые функции assign-operation могут определять предикаты произвольно.

Какой будет эквивалентная, идиоматическая конструкция в Clojure?

EDIT: Код выше взят из "The Art of the Propagator", авторы Алексей Радул и Джеральд Суссман.

11
задан 4 October 2011 в 01:14
поделиться