Я работаю над отличной книгой Let Over Lambda, и я пытаюсь перенести код Common Lisp на defunits на Clojure.Backquote without parens
Ниже генерирует макрос, который должен принять
(defn defunits-chaining [u units prev]
(if (some #(= u %) prev)
(throw (Throwable. (str u " depends on " prev))))
(let [spec (first (filter #(= u (first %)) units))]
(if (nil? spec)
(throw (Throwable. (str "unknown unit " u)))
(let [chain (second spec)]
(if (list? chain)
(* (first chain)
(defunits-chaining
(second chain)
units
(cons u prev)))
chain)))))
(defmacro defunits [quantity base-unit & units]
`(defmacro ~(symbol (str "unit-of-" quantity))
[valu# un#]
`(* ~valu#
~(case un#
~base-unit 1
[email protected](map (fn [x]
`(~(first x) ;; <-- PRETTY SURE IT'S THIS `(
~(defunits-chaining
(first x)
(cons `(~base-unit 1)
(partition 2 units))
nil)))
(partition 2 units))))))
(defunits time s m 60 h 3600)
и превратить его в макрос, который можно назвать как
(unit-of-time 4 h)
и дают результаты в базовом блоке (секунд в Это дело). Я думаю, что проблема заключается в изменении Clojure/CL api в «case». "Дело" в CL выглядит следующим образом:
(case 'a (('b) 'no) (('c) 'nope) (('a) 'yes))
но в Clojure ...
(case 'a 'b 'no 'c 'nope 'a 'yes)
КАК УДОБНО. Я изменил свою функцию Анон в гнездовой defmacro, но она продолжает генерировать как
(case un#
s 1
(m 60)
(h 3600)
Как я могу предотвратить эти внешние круглые скобки?
+1 для идеального описания 'flatten' –
Это именно то, что я искал раньше. Думаю, мне нужно кое-что сделать в стандартных функциях clojure. –
Да, снова глядя на вопрос, это * правильный ответ. –