Я бы попробовал уменьшить количество повторений.Я настроил функцию, чтобы использовать ваш макро-подход к аккумулятору, и пусть replace-templates*
сделает все остальное через (apply str ...)
.Таким образом можно повторно использовать функцию в макросе.
(defn extract-snippets
[^String text m]
(loop [text text
snippets []]
(cond
(zero? (count text))
snippets
(.startsWith text "{")
(let [brace (.indexOf text "}")]
(if (neg? brace)
(conj snippets text)
(if-let [[_ replacement] (find m (subs text 1 brace))]
(recur (subs text (inc brace)) (conj snippets replacement))
(recur (subs text 1) (conj snippets \{)))))
:else
(let [brace (.indexOf text "{")]
(if (neg? brace)
(conj snippets text)
(recur (subs text brace) (conj snippets (subs text 0 brace))))))))
(defn replace-templates*
[text m]
(apply str (extract-snippets text m)))
(defmacro replace-templates
[text m]
(if (map? m)
`(apply str ~(extract-snippets text m))
`(replace-templates* ~text ~m)))
Примечание: в макросе вы не ставили m
в кавычки.Так что это работает только потому, что раньше вы это делали.Это не было бы с (let [m {"a" "b"}] (replace-templates "..." m))
.