Использование команды *e
var из REPL Я распечатал трассировку стека.
clojure.lang.ArityException: Wrong number of args (-1) passed to: user/bar
Compiler.java:6557 clojure.lang.Compiler.macroexpand1
core.clj:3703 clojure.core/macroexpand-1
core.clj:3712 clojure.core/macroexpand
Это указывает на метод clojure.lang.Compiler.macroexpand1
в Compiler.java
, где я нашел эту строку:
throw new ArityException(e.actual - 2, e.name);
Если это e.actual
1
результат -1
для первого аргумента ArityException
конструктора. Там есть билет JIRA here, в котором упоминается это очень запутанное сообщение ArityException
.
Основываясь на том, что этот билет говорит, я начал искать ArityException
где-то еще, и нашли его в использовании count
и vec
, как будто exp
всегда был список.
Проблема заключается в том, что при вызове макроса bar
рекурсивно аргумент фактически символtail
, который не является сбор и этот вызов фактически макро расширяется, когда сам макрос создается не, когда она вызывается.
Изменение кода для макроса, так что он учитывает возможные значения, которые не являются списками, устраняет проблему, хотя я думаю, что полученный макрос не сделает то, что вы искали.
(defmacro bar' [exp]
(prn exp)
(let [length (if (seq? exp) (count exp) 0)]
(cond
(= length 0) '()
(= length 1) exp
:else
(let [[head & tail] (if (seq? exp) (vec exp) [exp])
[new-tail] (bar' tail)]
`(trap (~head [email protected]))))))
;; tail
(macroexpand '(bar' (inc 1)))
;; (inc 1)
;;= (user/trap (inc))
Я полностью забыл о проверке '* e', я новичок в Clojure. Но спасибо за ссылку и упоминание '* e' var, ваш пост помог! – Petesta
@Petesta Я нашел проблему. Пожалуйста, проверьте ответ выше. –
Спасибо, что нашли это и объяснили! Это было очень полезно. – Petesta