Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's wrong with this use of rest params with defprotocol and defrecord in Clojure?

What's wrong with the below use of rest params with defprotocol and defrecord in Clojure?

(defprotocol prot
  (f [this] [this & rest]))

(defrecord rec []
  prot
  (f [this] "one arg")
  (f [this & rest] "more than one arg"))

(prn (f (rec.)))
; (prn (f (rec.) 5))
(prn (f (rec.) 5 6))
; (prn (f (rec.) 5 6 7))

The above code prints the output I expect:

"one arg"
"more than one arg"

But if I uncomment either of the commented lines, I get the below exception:

Exception in thread "main" java.lang.IllegalArgumentException: No single method: f of interface: user.prot found for function: f of protocol: prot (bug.clj:10)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:5376)
    at clojure.lang.Compiler.analyze(Compiler.java:5190)
    at clojure.lang.Compiler.analyze(Compiler.java:5151)
    at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3057)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:5371)
    at clojure.lang.Compiler.analyze(Compiler.java:5190)
    at clojure.lang.Compiler.analyze(Compiler.java:5151)
    at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:4670)
    at clojure.lang.Compiler$FnMethod.parse(Compiler.java:4328)
    at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3173)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:5367)
    at clojure.lang.Compiler.analyze(Compiler.java:5190)
    at clojure.lang.Compiler.eval(Compiler.java:5421)
    at clojure.lang.Compiler.load(Compiler.java:5857)
    at clojure.lang.RT.loadResourceScript(RT.java:340)
    at clojure.lang.RT.loadResourceScript(RT.java:327)
    at clojure.lang.RT.loadResourceScript(RT.java:319)
    at clojure.main$load_script.invoke(main.clj:220)
    at clojure.main$script_opt.invoke(main.clj:273)
    at clojure.main$main.doInvoke(main.clj:354)
    at clojure.lang.RestFn.invoke(RestFn.java:409)
    at clojure.lang.Var.invoke(Var.java:365)
    at clojure.lang.AFn.applyToHelper(AFn.java:163)
    at clojure.lang.Var.applyTo(Var.java:482)
    at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: No single method: f of interface: user.prot found for function: f of protocol: prot
    at clojure.lang.Compiler$InvokeExpr.<init>(Compiler.java:2880)
    at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3063)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:5371)
    ... 24 more

Why is this?

like image 431
OpenSauce Avatar asked Nov 14 '11 09:11

OpenSauce


1 Answers

As far as I can tell, protocols do not support variadic arguments. What's probably happening is that "&" is taken as an argument symbol instead of a variadic indicator / list comprehension.

like image 142
Joost Diepenmaat Avatar answered Nov 07 '22 19:11

Joost Diepenmaat