Simple variations on state machines in Clojure

unsorted — cgrand, 3 March 2009 @ 15 h 00 min

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.

rest vs drop

unsorted — cgrand, 23 February 2009 @ 18 h 20 min

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.

Shadowing global names

unsorted — cgrand, 31 January 2009 @ 10 h 45 min

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:

  • it doesn’t work if the value of your var is not invokable,
  • it evaluates to something different: it returns the var an not its value. It happens that vars proxy function calls to their values but a var can be rebound:
    (def a (map str (range 10)))
    (def b (map #'str (range 10)))
    (take 5 a)
    <i>("0" "1" "2" "3" "4")</i>
    (take 5 b)
    <i>("0" "1" "2" "3" "4")</i>
    (binding [str identity] (doall a))
    <i>("0" "1" "2" "3" "4" "5" "6" "7" "8" "9")</i>
    (binding [str identity] (doall b))
    <i>("0" "1" "2" "3" "4" <strong>5 6 7 8 9</strong>)</i>

NB: @#'var-name is better than #'var-name but, really, just use the namespaced symbol.

Enlive: yet another HTML templating library

unsorted — cgrand, 19 January 2009 @ 16 h 04 min
[UPDATE] I have rewritten Enlive, this posts doesn’t work with the actual Enlive.

Enlive is a selector based templating library.
Its main design goal is to decouple html and presentation code, that’s why Enlive templates are plain old html files (it will ease roundtripping with designers).
In code, you have to declare where (using CSS-like selectors) and how (using clojure code) to alter the html template.
The resulting templating functions are compiled (the html tree isn’t transformed at runtime) and yields a seq of strings.

Here is an example:

(deftemplate microblog-template "net/cgrand/enlive_html/example.html" [title posts]
  [:title] title
  [:h1] title
  [:div.no-msg] (when-not (seq posts) ~(html/show))
  [:div.post] (for [{:keys [title body]} posts]
           ~(at
              [:h2] title
              [:p] body)))

;; at the repl:
net.cgrand.enlive-html.examples=> (apply str (microblog-template "Hello user!"
             [{:title "post #1"
               :body "hello with dangerous chars: <>&"}
              {:title "post #2"
               :body "dolor ipsum"}]))

<em>"&lt;html>&lt;head>&lt;title>Hello user!&lt;/title>&lt;/head>
&lt;body>&lt;h1>Hello user!&lt;/h1>
&lt;div class=\"post\">&lt;h2>post #1&lt;/h2>
&lt;p>hello with dangerous chars: &amp;lt;&amp;gt;&amp;amp;&lt;/p>&lt;/div>
&lt;div class=\"post\">&lt;h2>post #2&lt;/h2>
&lt;p>dolor ipsum&lt;/p>&lt;/div>&lt;/body>&lt;/html>"</em>

(NB: manually edited to add linebreaks.)

(Disclaimer: original idea by Ozzilee)

Surprising

unsorted — cgrand, 19 November 2008 @ 21 h 46 min
user=> (time (dotimes [i 100000000] [i]))
"Elapsed time: 5928.406543 msecs"
nil
user=> (time (dotimes [i 100000000] #(i)))
"Elapsed time: 1774.025749 msecs"
nil

So, it seems that creating a closure is faster than creating a vector. Cool.

Clojure Golf: fib-seq

unsorted — cgrand, 30 October 2008 @ 0 h 45 min

Revisiting a classic:

(def fib-seq
  (lazy-cat [0 1] (map + fib-seq (rest fib-seq))))

Clojure Golf: subsets-by-card (2)

unsorted — cgrand, 22 October 2008 @ 10 h 14 min

I wasn’t happy with the last one. At least this one is lazier and in increasing cardinality order.

(defn subsets-by-card [s]
  (reduce (fn [ssbc x]
           (map (fn [a b] (concat a (map #(conj % x) b)))
             (concat ssbc [nil]) (concat [nil] ssbc)))
    [[#{}]] s))

Decreasing order:

(defn subsets-by-card-reverse [s]
  (reduce (fn [ssbc x]
            (map (fn [a b] (concat a (map #(<ins>disj</ins> % x) b)))
              (concat ssbc [nil]) (concat [nil] ssbc)))
    [[<ins>(set s)</ins>]] s))

Clojure Golf: subsets-by-card

unsorted — cgrand, 20 October 2008 @ 23 h 09 min
(defn subsets-by-card [s]
  (reduce (fn [ssbc x]
            (concat
              (map (fn [a b] (concat a (map #(conj % x) b)))
                (cons nil ssbc) ssbc)
              [[#{}]]))
    [[#{}]] s))

(a tough one)

Clojure Golf: subsets

unsorted — cgrand, @ 23 h 08 min
(defn subsets [s]
  (reduce (fn [ss x] (concat ss (map #(conj % x) ss))) [#{}] s))

Clojure Golf: combinations (2)

unsorted — cgrand, 19 October 2008 @ 9 h 41 min
(defn combinations [& cs]
  (reduce #(for [v %1 i %2] (conj v i)) [[]] cs))
« Previous PageNext Page »
(c) 2012 Clojure and me | powered by WordPress with Barecity