2015-01-29 3 views
0

Существует макрос, и я пытаюсь вычислить эту ошибку ArityException Wrong number of args (-1) passed to: user/bar clojure.lang.Compiler.macroexpand1 (Compiler.java:6557). Я попытался отлаживать, но я не понимаю, почему существует арность (-1), когда я пытаюсь расширить макрос.ArityException с arity of (-1)

У меня есть следующий код.

(defn foo [x] (println x)) 

(defmacro bar [exp] 
    (let [length (count exp)] 
    (cond 
     (= length 0) '() 
     (= length 1) exp 
     :else (let [[head & tail] (vec exp) 
        [new-tail] (bar tail)] 
     `(trap (~head [email protected])))))) 

(macroexpand '(bar (inc 1))) 

У любого есть идеи относительно того, что происходит с arity (-1)?

ответ

2

Использование команды *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.actual1 результат -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)) 
+0

Я полностью забыл о проверке '* e', я новичок в Clojure. Но спасибо за ссылку и упоминание '* e' var, ваш пост помог! – Petesta

+0

@Petesta Я нашел проблему. Пожалуйста, проверьте ответ выше. –

+0

Спасибо, что нашли это и объяснили! Это было очень полезно. – Petesta

Смежные вопросы