On Wed, Dec 29, 2010 at 1:29 PM, Andreas Kostler
<andreas.koestler.le...@gmail.com> wrote:
>
> On 30/12/2010, at 2:39 AM, Mark Engelberg wrote:
>
>> I recommend reading:
>> http://htdp.org/2003-09-26/Book/curriculum-Z-H-16.html#node_sec_12.2
>> for a detailed discussion of how to design and write insertion sort in
>> a functional language, using linked lists and recursion.
> That's what I was looking for. However, Ken's version was a real eye opener :)
> Thanks

Andreas,

Unfortunately, Ken's version doesn't work on large lists, and suffers
from the nested-laziness problem that everyone's been talking about.
It's worth studying his code, though, because it's actually a great
illustration of how you have to be super-careful when working with
laziness, and how laziness sometimes makes it very hard to determine
runtime performance characteristics.

Using his code, try (first (insertion-sort (range 10000))).  I'm using
Sun's JVM, in -server mode, and this generates a stack overflow.

Aside from that problem, there are a few other details worth
mentioning about his version.  The split-with causes the first part of
the list (up to the insertion point) to be traversed twice, which is
somewhat more inefficient than it needs to be.  BTW, the use of concat
is where the nested laziness problem creeps in.  His clever use of
reduce unfortunately makes this not a "stable sort", because elements
that compare as equal will end up having their orders reversed.
(Doesn't matter if you're only sorting numbers, but could matter if
you're sorting records based on some field).

So again, I encourage you to first start by porting the Htdp version
of to Clojure.  It's always good to start with the clearest, most
elegant "classic" implementation.  Here's how it looks (adapted to
sort in increasing, rather than decreasing order):

(defn insert [n alon]
   (cond
    (empty? alon) (cons n nil)
    (<= n (first alon)) (cons n alon)
    (> n (first alon)) (cons (first alon) (insert n (rest alon)))))

(defn isort [alon]
  (cond
   (empty? alon) nil
   (seq? alon) (insert (first alon) (isort (rest alon)))))

This is a fairly literal translation to Clojure.   It works, but in
Clojure, generates a stack overflow on large lists.
Now, the question you should ask yourself is:
What are the minimal changes I can make to this code to eliminate the
stack overflow problem?

This will be a valuable exercise that will help you with all Clojure
code you write later, so make sure you can answer this question before
trying to get all fancy :)  Ask if you need further assistance...

-- 
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
Note that posts from new members are moderated - please be patient with your 
first post.
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