Skip to content

Instantly share code, notes, and snippets.

@RickMoynihan
Created May 3, 2012 23:42
Show Gist options
  • Select an option

  • Save RickMoynihan/2590472 to your computer and use it in GitHub Desktop.

Select an option

Save RickMoynihan/2590472 to your computer and use it in GitHub Desktop.
Symbol abuse, to get escape free SQL strings in Clojure
(defn &&* [symbol-seq]
"escape free strings"
(apply str (interpose " " symbol-seq)))
(&&* '(SELECT "users.*" FROM "users" WHERE ("users.username" = ?) ORDER BY "users.created" ASC))
;; => "SELECT users.* FROM users WHERE (\"users.username\" = ?) ORDER BY users.created ASC"
(defmacro && [& args]
"Use the macro if you can't live with having to quote a list when using &&*"
(&&* args))
(&& SELECT "users.*" FROM "users" WHERE ("users.username" = ?) ORDER BY "users.created" ASC)
;; => "SELECT users.* FROM users WHERE (\"users.username\" = ?) ORDER BY users.created ASC"
;; now quotes strings... unfortunately this means you can't use strings for reader characters.... keywords maybe? :-)
(defn &&* [symbol-seq]
(apply str
(interpose " "
(map (fn [s]
(if (string? s)
(str \" s \")
s))
symbol-seq))))
@scottlowe

Copy link
Copy Markdown

This is all good - I've learned a great deal about Clojure's Java innards and how the Reader works. I've also learned that I should have implemented a Dispatch Macro instead of a top level Reader Macro (although it's pretty much the same thing), which frees up more ASCII codes, so I've now done that. You get to choose the delimiter which follows the '#?'.

Output from my REPL:

user=> (println #?'abc def')
abc def
nil
user=> (println #?|abc"de "" e f|)
abc"de "" e f
nil
user=> (println #?:abc \n "d" e:)
abc \n "d" e
nil

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment