- What’s wrong with this code
(do (defmacro foobar [x] (doto x println)) (foobar (+ 1 1)))
?
- Nothing.
- Run it again.
- The first time,
foobar
is treated as a function (its argument has been evaluated) because foobar
is unknown before the whole top-level expression is compiled.
The second time, the var named foobar
preexists and is a macro, (foobar (+ 1 1))
is expanded.
This behaviour bit me while using with-test
to test macros. It’s the kind of bug that goes unnoticed while developing incrementally and evaluating in the same REPL, it was waiting for me to start a fresh REPL.
net.cgrand.enlive-html=> (sniptest "<div id=user-data>"
[:#user-data] (html-content "code injection<script>alert('boo')</script>")
[:#user-data (but #{:p :br :a :strong :em})] nil)
"<html><body><div id=\"user-data\">code injection</div></body></html>"
You also need to remove most attributes but it’s just a demo of something that was impossible with the old Enlive.
By the way, the old Enlive is no more. Long live the new Enlive!
Make it work, make it right, make it fast.
- Make it work
- sort of done: the old Enlive,
- Make it right
- work in progress, the new Enlive,
- Make it fast
- once the “right” branch is merged into master.
See the README file to know what’s new and here for an example.
I wanted to apply a function to every second item in a coll. I was considering writing something using interleave
, take-nth
and map
or a combination of mapcat
and partition
when I thought of this:
(map #(%1 %2) (cycle [f identity]) coll)
I really love clojure’s map parallel processing. (I should ask if every?
and some
could be allowed to take several colls.)
I needed to update a seq as follows: apply a given function to items at specified indices and insert the result (a seq) in place.
My first laborious attempt involved extracting subseqs of untouched items, mapping the function on the remaining items then joining everything back. Bleh! (Really, I don’t like indices but this time I haven’t found a way to work around.)
I was sad when, suddenly, I found this shortest solution:
(defn mapsplice [f coll indices]
(let [need-splice (map (set indices) (iterate inc 0))]
(mapcat #(if %2 (f %1) [%1]) coll need-splice)))
;; (mapsplice #(repeat % %) (range 10) [7 3])
;; (0 1 2 3 3 3 4 5 6 7 7 7 7 7 7 7 8 9)
Given a transition function that takes the current state and an input value as arguments then (reduce transition-fn initial-state input)
returns the final state.
If you are interested in intermediate states, you can use clojure.contrib.seq-utils/reductions instead of reduce.
If you want an asynchronous state machine, you can use an agent:
(def agt (agent initial-state))
;then each time you get an input-value:
(send agt transition-fn input-value)
If you add a watch to the agent, you can react to state transitions.
Now that fully lazy sequences are in the trunk, (rest a-seq)
and (drop 1 a-seq)
aren’t equivalent anymore:
user=> (def s (map #(do (println %) %) (range 10)))
#'user/s
user=> (def d (drop 1 s))
#'user/d
user=> (def r (rest s))
0
#'user/r
As one can see rest
needs to realize the first element of s while drop
doesn’t. The corollary is that (drop n s)
holds on the whole seq (including the nth first elements) while rest
computes the first element and then discards it.
A nice article on Clojure that gives one wrong tip: to use #'var-name
to access a shadowed global.
Don’t do that! You’d better use namespace-where-defined-or-alias/var-name
.
There are several reasons not to use #'var-name
:
NB: @#'var-name
is better than #'var-name
but, really, just use the namespaced symbol.
You can try clojure libs straight from the cloud:
(add-classpath "http://clojure-contrib.svn.sourceforge.net/viewvc/clojure-contrib/trunk/src/") ; sourceforge
(add-classpath "http://github.com/Lau-of-DK/clojureql/raw/master/src/"); github
(require '[clojure.contrib.duck-streams :as duck])
(require '[dk.bestinclass.clojureql :as ql])
Disclaimer:
add-classpath
is not meant to be used anywhere but at the repl,
- you’d better trust what you download,
- if you are unlucky you can get an inconsistent snapshot,
- use at your own risk!
This morning on #clojure erohtar asked:
what is the best way to bind vars to a value when sending to an agent?
I don’t know if it’s the best way but it’s mine:
(defmacro capture-and-send
"Capture the current value of the specified vars and rebind
them on the agent thread before executing the action."
[vars agent action & args]
(let [locals (map #(gensym (name %)) vars)]
`(let [~@(interleave locals vars)
action# (fn [& args#]
(binding [~@(interleave vars locals)]
(apply ~action args#)))]
(send ~agent action# ~@args))))
;; usage:
(capture-and-send [*out*] a f b c)
I post it here because erohtar needed it, I needed it once so others may need it.