Infixup: DWIM hoisting and splicing in the reader

3 views
Skip to first unread message

Per Vognsen

unread,
Mar 31, 2010, 8:41:28 AM3/31/10
to clo...@googlegroups.com
I spent the last few days sick in bed in a Jakarta hotel room without
any Internet. What little lucidity I had was spent on odd hacks. One
of them was particularly neat or particularly nasty depending on your
perspective.

It is a reader extension for list hoisting and splicing. You can write
(a `b` c) and it will be read as (b a c). It is right recursive, so
that (a `b` c `d` e) is read as (b a (d c e)). When the unhoisted
segments are lists of length greater than one, they are wrapped in a
singleton list rather than spliced. Thus (a b `c` d e) is read as (c
(a b) (d e)). The splicing and hoisting tries to have a natural DWIM
feel.

While this lets you perform surgery on any lists in the reader, its
strongest point is obviously infix function applications. Thus you can
write x `+` y `+` z. The mechanics of hoisting and splicing is such
that all infix operators are effectively right associative with
uniform precedence. Thus x `*` y `+` z is read as (* x (+ y z)).

Here is a quick demo transcript from the REPL:

Clojure 1.2.0-master-SNAPSHOT
user=> (defn dwim [x] (if (coll? x) (vec x) [x]))
#'user/dwim
user=> (defmacro => [bindings body] `(fn ~(dwim bindings) ~body))
#'user/=>
user=> (defmacro where [body bindings] `(let ~(dwim bindings) ~body))
#'user/where
user=> (defmacro || [body bindings] `(for ~(dwim bindings) ~body))
#'user/||
user=> (def add (x y `=>` x `+` y))
#'user/add
user=> (add 3 5)
8
user=> (def curried-add (x `=>` y `=>` x `+` y))
#'user/curried-add
user=> ((curried-add 3) 5)
8
user=> ((x `+` y `+` z) `where` x 3, y (x `+` 2), z (x `*` y))
23
user=> ((x `+` y) `||` x (range 10), y (range 10), :when (even? x))
(0 1 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9 10 11 4 5 6 7 8 9 10 11 12 13 6 7
8 9 10 11 12 13 14 15 8 9 10 11 12 13 14 15 16 17)
user=> (0 `cons` 2 `cons` [1 2] `(map +)` [3 4])
(0 2 4 6)

I gisted my diff, in case anyone wants to play around with this:

http://gist.github.com/350244

I withhold judgement on its ultimate merits. :)

-Per

Reply all
Reply to author
Forward
0 new messages