2012-05-16 28 views
6

Tôi muốn có một chức năng trong loại của tôi có một đối số tùy chọn. Tôi đã sử dụng thành công các đối số tùy chọn trong các hàm không thuộc về một kiểu, tuy nhiên, tôi dường như không thể làm cho nó hoạt động trong một giao thức và kiểu.Làm thế nào để sử dụng các đối số tùy chọn trong defprotocol?

thử nghiệm thất bại của tôi:

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

Trả lời

8

Như đã trả lời here, các giao thức không hỗ trợ varargs. Bạn phải định nghĩa một phương thức riêng cho mỗi số đối số được yêu cầu hoặc đơn giản là chấp nhận một danh sách làm đối số.

+1

thanks a lot. là một người mới bắt đầu Clojure, tôi thực sự mong rằng các thông báo lỗi của nó có thể có ý nghĩa gì đó. –

+3

+1. Nhưng đáng nói thêm rằng một giải pháp tốt là tạo ra một phương thức bên ngoài giao thức mà * có * hỗ trợ varargs, và có hàm này gọi hàm thích hợp (s) trong chính giao thức đó – mikera

2

Tôi đã thực hiện defprotocol+ để bạn xác định giao thức với các đối số tùy chọn. Ý tưởng là để làm cho & args như một đối số cố định trong giao thức và tạo ra một hàm bao bọc tự động.

Khám phá this gist cho macro.

Cách sử dụng

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

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

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

Các vấn đề liên quan