I have a suspicion that a serious implementation of this may exist,
please let me know if that is so!
Cheers,
Victor Rodriguez.
;;; A toy to experiment with Clojure macros.
;;;
;;; (f "1 + 2 = ~(+ 1 2)") results in "1 + 2 = 3"
;;;
;;; Know of a real implementation of this? Please Let me know at
;;; vic...@gmail.com.
(defn tokenize
"Split a string into a sequence of plain strings and
''unquoted'' form-strings. For example, it turns
\"~a = ~(- b c)\" into (\"~a\" \" = \"~(- b c)\")"
[s]
(let [unquote-re
(re-pattern
(str "~\\([^\\)]*\\)" ; a tilde followed by a paren
"|"
"~\\w+" ; a tilde not followed by an open paren...
"|"
"[^~]+" ; anything that is not a tilde
"|"
"~$"))] ; a tilde at the end
(re-seq unquote-re s)))
(defn to-form
"Convert a strings to forms. For example, it turns
''~foo'' and ''~(inc a)'' into 'foo' and '(inc a)',
respectively."
[s]
(if (= \~ (first s))
(read-string (.substring s 1))
s))
(defn f*
"Convert a string with ''unquoted'' forms into a
list of strings and forms."
[s]
(loop [tokens (tokenize s)
form '(str )]
(if-let [token (first tokens)]
(recur (rest tokens)
(conj form (to-form token)))
(reverse form))))
(defmacro f
"Compile time string templates!"
[s]
(f* s))
(comment
(let [s "a + b ="
a 1
b 2
m {:title 'chihuahua }]
(f "let ~s ~(+ a b) and the title be ~(:title m)"))
)
Here is something I wrote as a Clojure learning exercise.
I have a suspicion that a serious implementation of this may exist,
please let me know if that is so!