I think your code works; in any case, List.concat is more like the LISP append. Here's the version I wrote that's a more idiomatic translation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 

(*
(defun quicksort (list)
   (let* ((x (car list)) (r (cdr list)) (fn (lambda (a) (a<x))) )
   (append (quicksort (remove-if-not fn r)) (list x) (quicksort(remove-if fn r))) ))
*)

let rec quicksort list =
    match list with
    | [] -> []
    | x::r ->
        let fn a = a < x
        List.concat [quicksort (r |> List.filter fn); [x]; quicksort (r |> List.filter (not<<fn))]

let r = quicksort [7;3;5;6;1;4;2]
printfn "%A" r    

By on 4/1/2010 3:02 PM ()

Thanks, and that's nice code.
I particularly like the fact that you can pattern a list into head::tail like that.
Interestingly though, it still does include a basis, if I am reading it right... |[] -> []
I actually don't know why the CL version doesn't need one - maybe there's some kind of basis implicit in 'append' or something like that.
Thanks again!

By on 4/1/2010 3:37 PM ()

In CL, if you have the empty list, the "car" and "cdr" don't throw an exception, they just return the empty list again. In F#, these (head/tail/pattern-match-with=::) throw.

By on 4/1/2010 3:50 PM ()

That's a good point. I remember from the little I've read that CL, in want of any other resolution, resolves to nil.
But what I wonder about more in the example is that there is any resolution at all.
For instance if I try something like this:

(defun infinitelist (L)
(cons(car L) (infinitelist(cdr L)) ))

I get "Program stack overflow" because it does not have a basis to return at null.
In other words, car<> and cdr<> return <> but a recursive funcall on <> keeps on returning <> ad finitum.
I still don't see how the quicksort does not cause a stack overflow.
I think it might have something to do with 'append' but I'm not sure to be honest.
I could just be missing something.

By on 4/1/2010 4:49 PM ()

For instance if I try something like this:

(defun infinitelist (L)
(cons(car L) (infinitelist(cdr L)) ))

I get "Program stack overflow" because it does not have a basis to return at null.
In other words, car<> and cdr<> return <> but a recursive funcall on <> keeps on returning <> ad finitum.
I still don't see how the quicksort does not cause a stack overflow.

Quicksort as it stands is not tail-recursive, and so on a big enough data, both the (fixed) CL and F# versions will stackoverflow. But it needs to be a very big list.

(That said, yes, looking more carefully back at your original CL code, it does just loop infinitely until stackoverflow, without a base case to prevent the recursive calls.)

By on 4/1/2010 5:13 PM ()

Great, thanks for the advice, the F# code, and the points about stack overflow, tail-recursion etc.
Sorry again about the dodgy code to begin with.

By on 4/2/2010 4:15 AM ()

actually scratch that, I think it might need a basis in CL too, which makes sense
i think i had a basis in a calling function
that's what i get for sprawling code
sorry about that
(how do you make the very-ashamed smiley?)

By on 4/1/2010 5:05 PM ()

by the way,
sorry about the formatting glitch - I got the F# formatting but that was the expense!

By on 4/1/2010 2:54 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper