dev dependencies| lein-clojars |
| 0.5.0-SNAPSHOT | | jline |
| 0.9.94 | | swank-clojure |
| 1.2.1 | | marginalia |
| 0.5.0-alpha |
|
(this space intentionally left blank) |
| |
| |
by Fogus - Feb. 9, 2011
http://github.com/fogus/evalive
| |
Various eval functions and macros.
| | (ns evalive.core)

| |
Map-every-other. Works like map except only on every other element.
| | (defn- map-eo
[f & colls]
(apply map
#(%1 %&)
(cycle [first #(apply f %)])
colls))
Looks up the value of a symbol at the time of compilation and quotes it. This will be useful later on.
| | (def ^{:private true
:doc }
compile-time-lookup
#(do `'~%))
Public API
| |
When called, lexical-context returns a map of symbol → value of the
current lexical bindings where the call occurred. For example:
(let [a 1]
(let [b 2]
(lexical-bindings)))
returns
{a 1, b 2}
TODO Explore the utility of a version that takes a map and returns the merge of the supplied
map and the lexical bindings.
| | (defmacro lexical-context
[]
(let [symbols (keys &env)]
(zipmap (map (fn [sym] `(quote ~sym))
symbols)
symbols)))
Defines the public interface to evilive's "contextual eval"® facilities. In a nutshell,
contextual eval refers to perform an eval that refers to lexical bindings in addition to namespace
bindings. You see, the core eval function, like and function, is not privy to the lexical context
in which it is run and is therefore of limited scope in its usefulness. However, evalive enhances
the stock eval by building a lexical context into the form under evaluation from various structures.
| | (defprotocol Evil
(evil [this form]))
lexical contexts defined in maps
| | (extend-type java.util.Map
Evil
(evil [this form]
(eval
`(let [~@(mapcat (fn [[k v]] [k `'~v])
this)]
~form))))
lexical contexts defined in sequentials (e.g. lists, vectors)
| | (extend-type java.util.List
Evil
(evil [this form]
(eval
`(let [~@(map-eo compile-time-lookup this)]
~form))))
lexical contexts defined in arrays
| | (extend-type (Class/forName "[Ljava.lang.Object;")
Evil
(evil [this form]
(evil (seq this) form)))
Provides a simple way to obtain a map of the lexical context based on the
result of a destructuring operation. That is, the typical call to the
destructure function will operate along the lines of:
(destructure '[[_ _ x _ _] [1 2 3 4 5]])
;=> [V [1 2 3 4 5]
_ (nth V 0 nil)
_ (nth V 1 nil)
x (nth V 2 nil)
_ (nth V 3 nil)
_ (nth V 4 nil)]
whereby the form returned contains the operations needed to pull apart (i.e. destructure)
the data structure under examination. However, destro will instead resolve the values
of the destructuring operation, including any intermediate bindings, as below:
(destro [a b [c d & e] :as Z]
[1 2 [3 4 5 6 7 8]])
;=> {vec__2330 [1 2 [3 4 5 6 7 8]],
a 1,
b 2,
vec__2331 [3 4 5 6 7 8],
c 3,
d 4,
e (5 6 7 8),
Z [1 2 [3 4 5 6 7 8]]}
This will also operate as expected within a lexical context:
(let [c [1 2]]
(destro [a b] c))
;=> {c [1 2],
vec__2336 [1 2],
a 1,
b 2}
| | (defmacro destro
[binds form]
`(let [~binds ~form]
(lexical-context)))
|
| | (comment
(evil '{message "Hello", place "Cleveland"}
'(println message place))
; Hello Cleveland
(destro [message place] ["Hello" "Cleveland"])
;=> {vec__2438 [Hello Cleveland], message Hello, place Cleveland}
(evil (destro [message place] ["Hello" "Cleveland"])
'(println message place))
; Hello Cleveland
)
| | |