2012-04-17 3 views
0

Я пытаюсь использовать тип намека, чтобы различать два метода с одним аргументом.Как использовать тип hinting для создания многомерного метода Clojure с переменным числом аргументов?

Например, добавление вершины оборачивают метод Java, который может принимать переменное число аргументов, и поэтому здесь я пытаюсь сделать надстройку вершины взять ноль, один или два аргумента ...

(defmulti add-vertex (fn [& args] (map class args))) 
(defmethod add-vertex [] (add-vertex nil nil)) 
(defmethod add-vertex Integer [id] (add-vertex id nil)) 
(defmethod add-vertex Map [props] (add-vertex nil props)) 
(defmethod add-vertex [Integer Map] [id props] 
    ((let [vertex (. *g* addVertex id)] 
    (when props 
     (apply set-props vertex (interleave (map name (keys props)) (vals props)))) 
    vertex))) 

Обратите внимание, что есть две функции singe-arg - каждый из которых принимает другой тип (id - это Java Integer, а реквизит - карта Java). Я новичок в Clojure, поэтому я подозреваю, что делаю это совершенно неправильно.

ответ

2

Вот код для того, что вы пытаетесь сделать:

(defmulti add-vertex (fn [& args] (map class args))) 
(defmethod add-vertex [] [] (add-vertex nil nil)) 

;; You could also use java.lang.Integer here, but numbers are Longs by default 
(defmethod add-vertex [java.lang.Long] [id] 
             (add-vertex id nil)) 

;; I assume you are using a clojure map ie {:1 2} 
(defmethod add-vertex [clojure.lang.PersistentArrayMap] [props] 
                 (add-vertex nil props)) 

(defmethod add-vertex [java.lang.Long clojure.lang.PersistentArrayMap] [id props] ...) 

Но как вы можете видеть это становится довольно грязным с классами.

Альтернативным решением может быть, чтобы сделать что-то вроде этого:

(defn dispatch-fn 
    ([] :empty) 
    ([a] (cond 
     (number? a) :number 
     (map? a) :map 
     :else  :error)) 
    ([a b] (if (and (number? a) (map? b)) 
      :number-and-map 
      :error)) 
    ([a b & args] :error)) 

(defmulti add-vertex dispatch-fn) 
(defmethod add-vertex :empty [] (add-vertex nil nil)) 
(defmethod add-vertex :number [id] (add-vertex id nil)) 
(defmethod add-vertex :map [props] (add-vertex nil props)) 
(defmethod add-vertex :number-and-map [id props] ...) 
(defmethod add-vertex :error [& args] ...) 
0

Вы не используете тип-намек, но записываете литералы класса как значения, по которым будет оцениваться функция отправки. Ваша проблема в том, что вы не включаете все типы в векторе - даже когда есть только один.

Я тепло предлагаю вам read up по многоточным технологиям.