2012-05-16 20 views
6

İsteğe bağlı bir argümanı alan türümde bir işlev istiyorum. Bir türe ait olmayan işlevlerde isteğe bağlı argümanları başarılı bir şekilde kullandım, ancak bir protokol içinde çalışıp yazamadım.İsteğe bağlı argümanlar defprotocol'da nasıl kullanılır?

Benim başarısız deneme:

Clojure 1.4.0 
user=> (defprotocol OptArg 
(func [this a & b])) 
OptArg 

user=> (deftype Imp [] OptArg 
(func [this a & b] (println a b))) 
user.Imp 

user=> (func (Imp.) 1 2) 
CompilerException java.lang.IllegalArgumentException: No single method: func of interface: user.OptArg found for function: func of protocol: OptArg, compiling:(NO_SOURCE_PATH:5) 

user=> (defn opt-arg [a & b] (println a b)) 
#'user/opt-arg 

user=> (opt-arg 1 2) 
1 (2) 
nil 
user=> (opt-arg 1) 
1 nil 
nil 
user=> 

cevap

8

gibi, protokoller varargs desteklemeyen here cevap verdi. Gerekli her bir argüman sayısı için ayrı bir metot tanımlamanız veya bir listeyi argüman olarak kabul etmeniz gerekir.

+1

çok teşekkürler. Clojure yeni başlayan biri olarak, hata mesajlarının bir anlamda anlamlı olmasını diliyorum. –

+3

+1. Ancak, iyi bir çözümün, protokolün dışında * verinin * desteklendiğini ve bu işlevin protokolün kendisinde uygun işlev (ler) i çağırmasını sağlayan bir yöntem oluşturmak olduğunu eklemeye değer. – mikera

2

İsteğe bağlı argümanlar ile protokol tanımlamanız için bir defprotocol+ yaptım. Fikir, protokolde sabit bir argüman olarak & args yapmak ve otomatik olarak bir sarmalayıcı işlevi oluşturmaktır. Makro için this gist'a bakın.

Kullanımı

 
(defprotocol+ IPipeline 
    (run-and-wait [this & args])) 

(defrecord+ Pipeline [] 
    IPipeline 
    (run-and-wait [this & args] 
    )) 

(run-and-wait (Pipeline.) 1 2 3 4 5) 

İlgili konular