2012-05-16 11 views
6

Quiero tener una función en mi tipo que toma un argumento opcional. He utilizado con éxito argumentos opcionales en funciones que no pertenecen a un tipo, sin embargo, parece que no puedo hacerlo funcionar dentro de un protocolo y tipo.¿Cómo usar argumentos opcionales en defprotocol?

Mi ensayo fallido:

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=> 

Respuesta

8

como respondida here, los protocolos no son compatibles con varargs. Debe definir un método diferente para cada número requerido de argumentos o simplemente aceptar una lista como argumento.

+1

muchas gracias. como principiante en Clojure, realmente deseo que sus mensajes de error tengan algún sentido. –

+3

+1. Pero vale la pena agregar que una buena solución es crear un método fuera del protocolo que * does * support varargs, y hacer que esta función llame a la (s) función (es) apropiada (s) en el protocolo mismo – mikera

2

Hice un defprotocol+ para que pueda definir el protocolo con argumentos opcionales. La idea es hacer & args como un argumento fijo en el protocolo y crear una función de envoltura automáticamente.

Consulte this gist para macro.

Uso

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

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

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

Cuestiones relacionadas