Я вижу по крайней мере одну возможную ошибку в вашем коде: [fir sec & res]
должно быть [fir sec res]
, так как вам нужен третий аргумент, а не список всех аргументов. Это все еще не решает проблемы в вашем коде. Главное, что вы переосмысливаете это (eval
и прочее)
Я бы, наверное, использовал что-то вроде этого:
(defmacro infix [n]
(if (list? n)
(let [[arg1 op arg2] n]
`(~op (infix ~arg1) (infix ~arg2)))
n))
user> (clojure.walk/macroexpand-all '(infix (1 + ((6 - (3 / 7)) * 3))))
;;=> (+ 1 (* (- 6 (/ 3 7)) 3))
user> (infix (1 + ((6 - (3 / 7)) * 3)))
;;=> 124/7
ОБНОВЛЕНИЕ
чтобы опустить скобки, вы можете обновить его следующим образом:
(defn unwrap-arg [restargs]
(if (= 1 (count restargs))
(first restargs)
restargs))
(defmacro infix [n]
(if (list? n)
(let [[arg1 op & arg2] n]
`(~op (infix ~arg1) (infix ~(unwrap-arg arg2))))
n))
user> (clojure.walk/macroexpand-all '(infix (1 + 2 + (10 - (4 / 10)) + (4 * 5))))
;;=> (+ 1 (+ 2 (+ (- 10 (/ 4 10)) (* 4 5))))
user> (infix (1 + 2 + (10 - (4 / 10)) + (4 * 5)))
;;=> 163/5