Friday, April 17, 2009

Frequency table from sequences

Following function creates the frequency table from the given sequences.

(defn frequency-table  [& seqs]
(let [count-fn (fn [s item]
(update-in s [item] #(if % (inc %) 1)))]
(reduce #(reduce count-fn %1 %2) {} seqs)))

(frequency-table [1 2 3])
=> {3 1, 2 1, 1 1}

(frequency-table ["fred" "ethel" "lucy"] ["lucy" "rick"] ["lucy" "ethel" "john"])
=> {"john" 1, "rick" 1, "lucy" 3, "ethel" 2, "fred" 1}

(frequency-table '(1 2 3) #{4 2 1})
=> {4 1, 3 1, 2 2, 1 2}

(frequency-table {:a 1 :b 3} {:a 1 :b 4})
=> {[:b 4] 1, [:b 3] 1, [:a 1] 2}

Wednesday, April 15, 2009

Sorting the list of sequences using max-key

(max-key k x y)

max-key applies the k function (which should return integer) to the rest of the arguments and returns the argument which yields the greatest number. This can be used to bubble the largest sequence to the front.

(max-key count #{1 2 3} #{4 5})
=> #{1 2 3}

(max-key count #{1 2 3} #{4 5 6 7})
=> #{4 5 6 7}

(apply max-key count '(#{3 4 5} #{1 2} #{3}))
=> #{3 4 5}

Following function takes a list of sequences and return them in the order of their size. So the sequence with most number of elements are returned first.

(defn sort-seqs [seqs]
(lazy-seq
(when-not (empty? seqs)
(let [largest-seq (apply max-key count seqs)]
(cons largest-seq (sort-seqs (remove #(identical? largest-seq %) seqs)))))))

(sort-seqs '(#{3} #{3 4 5} #{1 2}))
=> (#{3 4 5} #{1 2} #{3})

(sort-seqs '([1 2] [3] [4 5 6 7]))
=> ([4 5 6 7] [1 2] [3])

(sort-seqs '({:a 1} {a 2 :b 4} {:c 5}))
=> ({a 2, :b 4} {:c 5} {:a 1})

Thursday, April 9, 2009

Manipulating an inner item - (in-place editing)

If you have nested associative structure than using assoc-in and update-in you can manipulate the inner structured item and get back a newly nested structure.

update-in takes the sequence of keys to find the location and a function to apply to the old value at that location:

(def m {:a [1 2 3]})
(update-in m [:a] conj 4)
=> {:a [1 2 3 4]}

Nested map update
(def m {:a {:b [1 2 3]}})
(update-in m [:a :b] conj 4)
=> {:a {:b [1 2 3 4]}}

Apply merge function to an inner map
(def m {:a 1 :config {:b 1}})
(update-in m [:config] merge {:b 3})
=> {:a 1, :config {:b 3}}

We can also apply the same functions to the vectors also. Vectors are associative maps and index are the keys.

(def v [:a {:c 2, :b 1} :d])
(v 2)
=> :d ;Item at the 3rd index

We can use both sequential and associative de-structuring binds on vectors:
(let [{fred 2} v]
fred)
=> :d

assoc-in also takes the sequence of keys and a new value. The following code is locating the 2nd item in the vector. assoc-in is adding the [:rows 42] key value pair to the found map and update-in is applying assoc to the found map with the given key value pairs.

(assoc-in v [1 :rows] 42)
=> [:a {:rows 42, :c 2, :b 1} :d]

(update-in v [1] assoc :rows 42 :cols 21)
=> [:a {:cols 21, :rows 42, :c 2, :b 1} :d]

Long term relationship function - Var object

When you pass a function to another function as parameter than the value of the function var is passed. So if you redefine the passed function - the other function still sees the old defined function and doesn't use the new function. So if you want to establish a long term relationship between the two functions - you need to pass the Var object itself and not its value.
e.g.

(defn worker []
(Thread/sleep 2000)
(prn "not working"))
Try two commands on the repl:
user> worker
#<user$worker__319 user$worker__319@cbb3fa>

user> (var worker)
#'user/worker

user> #'worker
#'user/worker

The reader macro #'x expands to (var x). If you have the following function which calls the worker function in a thread:
(defn worker-thread [worker-fn]
(.start (Thread. #(dotimes [i 10] (worker-fn)))))
Launch the worker thread

user> (worker-thread worker)

Fix the worker function:
(defn worker []
(Thread/sleep 2000)
(prn "working"))
You will see that the thread still printing "not working" every 5 seconds.

If you had launched the worker thread as follows:

user> (worker-thread #'worker)

and now you fix the function:
(defn worker []
(Thread/sleep 2000)
(prn "really working"))
Thread will now print the new "really printing" message.

Wednesday, April 1, 2009

Destructuring binding in def

A lot of times when I am debugging a clojure function in REPL. I end up doing defs for all my lets and if my let is using the destructuring bind than it become a little tedious process. The following macro helps me substitute the  let with def+ to define the symbols in my REPL:

(defmacro def+
  "def with binding (def+ [{:keys [a b d]} {:a 1 :b 2 :d 3}])"
  [bindings]
  (let [let-expr (macroexpand `(let ~bindings))
        vars (filter #(not (.contains (str %) "__"))
               (map first (partition 2 (second let-expr))))
        def-vars (map (fn [v] `(def ~v ~v)) vars)]
    (concat let-expr def-vars)))

;Example usage:
(def+ [a 1 b 2])
(def+ [{:keys [a b]} {:a 1 :b 2}])
(def+ [z 1
          {:keys [a b]} {:a 1 :b 2}])

This should not be used in the final code - though it will work - but probably using in REPL is a better use for this macro.