Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
方案->;Clojure:方法中有谓词的多方法?_Clojure_Scheme_Multimethod - Fatal编程技术网

方案->;Clojure:方法中有谓词的多方法?

方案->;Clojure:方法中有谓词的多方法?,clojure,scheme,multimethod,Clojure,Scheme,Multimethod,我正在将一些方案代码转换为Clojure。最初使用的调度模式与multimemethods非常相似,但对匹配谓词采用了反向方法。例如,有一个通用函数“分配操作”。具体的实现细节目前并不太重要,但请注意,它可以包含一系列参数谓词 (define (assign-operation operator handler . argument-predicates) (let ((record (let ((record (get-operator-record operator))

我正在将一些方案代码转换为Clojure。最初使用的调度模式与multimemethods非常相似,但对匹配谓词采用了反向方法。例如,有一个通用函数“分配操作”。具体的实现细节目前并不太重要,但请注意,它可以包含一系列参数谓词

(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)))))
分派函数提供这些谓词,函数的arity中每个参数一个谓词

(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”时,会询问每个处理程序是否对操作数有效

正如我所理解的多方法一样,分派函数是在一组实现中定义的,根据分派fn的返回值分派到特定的方法。在上述方案中,新的赋值操作函数可以任意定义谓词

在Clojure中,什么是等效的惯用构造


编辑:上面的代码来自Alexey Radul和Gerald Sussman。

使用Clojure的multimethods可以相当容易地做到这一点-诀窍是创建一个分派函数,区分不同的谓词集

最简单的方法可能是维护一个“复合谓词”向量,将所有单个谓词应用于完整参数列表,并使用该向量的索引作为分派值:

(def pred-list (ref []))

(defn dispatch-function [& args] 
  (loop [i 0]
    (cond
      (>= i (count @pred-list))     (throw (Error. "No matching function!"))
      (apply (@pred-list i) args)   i
      :else                         (recur (inc i)))))

(defmulti handler dispatch-function)

(defn assign-operation [function & preds]    
  (dosync
    (let [i (count @pred-list)]
      (alter pred-list conj   
             (fn [& args] (every? identity (map #(%1 %2) preds args))))
      (defmethod handler i [& args] (apply function args)))))  
然后,您可以创建操作来处理您喜欢的任何谓词,如下所示:

(assign-operation (fn [x] (/ x 2)) even?)

(assign-operation (fn [x] (+ x 1)) odd?)

(take 15 (iterate handler 77))
=> (77 78 39 40 20 10 5 6 3 4 2 1 2 1 2)

受苏斯曼的奇怪循环演讲启发?看起来像一张很酷的纸。是否应该读为“调用了泛型函数“merge”?无论如何,我认为最好的选择是存储在atom中的调度表。我认为多种方法在这方面没有帮助。我很想知道结果如何。是的,应该是“合并”。谢谢