Profile of Kean Santos

Personal Website

Posts

Clojure: implementing foldr

Clojure: foldr (fold right)

Immutability and State

Merge sort in Scala, part 2

Merge sort in Scala, part 1

Merge sort in Clojure, part 2

Trying out Clojure

31 October 2015

Merge sort in Clojure, part 2

by Kean Santos

I fixed up my merge function to use tail recursion, so that it would no longer explode with a stack overflow. To do this, I refactored the function to explicitly accumulate results in a new parameter, and then used ‘recur’ to make the recursive call.

I also found out that ‘let’ deals nicely with nils, so it was possible to do away with the input-checking function for the merge step.

The new implementation is below, and the output is identical to that of the original:

(ns test-mergesort)

(declare merge)
; mergesort implementation: keep splitting input into 2, then merge outputs.
(defn mergesort
  "experimental merge sort implementation"
  [v]
  (println "Sorting input: " v)
  (let [len (count v) ]
    (if (<= len 1) v
        (let [mid (/ len 2)
              left (subvec v 0 mid)
              right (subvec v mid)]
              (merge [] (mergesort left) (mergesort right))))))

; merge 2 sorted lists by taking elements of each list and  accumulating the smaller one into the output 
(defn- merge [acc left right]
  (println "Merging input: " left " , " right)
  (cond (empty? left) (into acc right)
        (empty? right) (into acc left)
        :else
        (let [[l & ll] left
              [r & rr] right
              [next-smallest next-left next-right]  (if (<= l r) [l ll right] [r left rr])
              next-acc (conj acc next-smallest)]
         (recur next-acc next-left next-right) )))


; Try it out on the following vector
( println "Result: " (mergesort [3 5 1 2 9 5 7 4]))
tags: