Thinking functionally is hard when you're used to programming
imperatively. So instead of leaping straight into Clojure, lets stick
with Python for the time being.

So let's take your Python code:

def msort(someList):
  myList = [[x] for x in someList]
  while len(myList) > 1:
    l1 = myList.pop(0)
    l2 = myList.pop(0)
    listmerge = some_merge_function(l1, l2)
    myList.append(listmerge)
  return myList[0]

(I'm assuming you meant msort(someList) and not msort(myList))

Remove all functions and methods that change their arguments, and
replace them with equivalent assignments:

def msort(someList):
  myList = [[x] for x in someList]
  while len(myList) > 1:
    l1 = myList[0]
    l2 = myList[1]
    myList = myList[2:]
    listmerge = some_merge_function(l1, l2)
    myList = myList + [listmerge]
  return myList[0]

Next we need to turn the while loop into a recursive function. We can
do this by identifying what the while loop changes (myList), and then
using that as the function's input and output:

def msort(someList):
  myList = [[x] for x in someList]
  def recursive_loop(myList)
    if len(myList) > 1:
      l1 = myList[0]
      l2 = myList[1]
      myList = myList[2:]
      listmerge = some_merge_function(l1, l2)
      myList = myList + [listmerge]
      myList = recursive_loop(myList)
      return myList
    else:
      return myList
  return recursive_loop(myList)[0]

Once you've replaced mutable functions and methods with assignments,
and replaced loops with recursive functions, you can convert your code
into Clojure:

(defn msort [some-list]
  (let
    [my-list (vec (map vector some-list))
     recursive-loop
      (fn [my-list]
        (if (> (count my-list) 1)
          (let [l1         (my-list 0)
                l2         (my-list 1)
                my-list    (rest (rest my-list))
                list-merge (some-merge-function l1 l2)
                my-list    (conj my-list listmerge)
                my-list    (recursive-loop my-list)]
            my-list)
          my-list))]
    ((recursive-loop my-list) 0)))

Now we have a functional program, it's time to start taking advantage
of all the nice Clojure functions and macros. Let's start with the
loop/recur form, which we can use to replace the recursive-loop
function:

(defn msort [some-list]
  (loop [my-list (vec (map vector some-list))]
    (if (> (count my-list) 1)
      (let [l1         (my-list 0)
            l2         (my-list 1)
            my-list    (rest (rest my-list))
            list-merge (some-merge-function l1 l2)
            my-list    (conj my-list listmerge)]
        (recur my-list))
      (my-list 0))))

Clojure also supports destructuring binding in let forms, so lets use
that:

(defn msort [some-list]
  (loop [my-list (vec (map vector some-list))]
    (if (> (count my-list) 1)
      (let [[l1 l2 & my-list] my-list
            list-merge       (some-merge-function l1 l2)
            my-list          (conj my-list list-merge)]
        (recur my-list))
      (my-list 0))))

And we can use rest to check if the list has more than one attribute:

(defn msort [some-list]
  (loop [my-list (vec (map vector some-list))]
    (if (rest my-list)
      (let [[l1 l2 & my-list] my-list
            list-merge       (some-merge-function l1 l2)
            my-list          (conj my-list list-merge)]
        (recur my-list))
      (first my-list))))

This could be neatened up a bit, but that's basically a functional
version of your algorithm.

- James
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to