qsort :: Ord a => [a] -> [a]
qsort [] = []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
where
lesser = filter (< p) xs
greater = filter (>= p) xs
I know nothing about Haskell but I don't think this code implements
the original quicksort algorithm which sorts the input in-place.
Moreover the two-pass of filter over the list and the concatenations
cause unnecessary overhead. Thus, even if the sample code is simple
and elegant, a real-world implementation would surely be a bit longer
than the given example.I wish more Haskell proponents would spent less time showing off simple and elegant code, and more time showing fast and correct code.
It's pretty elegant, too, if less than the inefficient pseudo-qsort shown by the OP.
EDIT: As a curious example, Clojure's sort function actually converts the sequence to a (Java) Array and calls java.util.Arrays.sort() on it, then turns it back into a sequence:
https://github.com/clojure/clojure/blob/b578c69d7480f621841e...
You can argue some older languages were written in a way in which it was (reasonably) easy to write a compiler that generates code with little performance overhead when compared to assembly (at worst a factor of 2 to 4, back in the 80s). Some popular languages keep adding abstractions and constructs that the compiler can actually deal with without some new compiler research breakthrough.
Nice thought. What's the purpose of showing code which you won't be using in a real-world application? Making you think the language is more expressive than what it really is?
Many people say Haskell code is elegant and concise. Would this be the case if code we were shown would be real-world Haskell?
Here's a page with some actual haskell quicksorts:
http://www.haskell.org/haskellwiki/Introduction/Direct_Trans...
qsort :: Ord a => [a] -> [a]
qsort [] = []
qsort [x] = [x]
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
where
(lesser, greater) = foldl split ([],[]) xs
where
split (left, right) x = if x<p then (left:x, right), else (left, right:x)
Does this work? split (left, right) x = if x<p then (x:left, right), else (left, x:right)* especially with naive pivot from the middle of array
And btw, here's the answer in F#:
let rec qsort = function
| [] -> []
| x::xs -> let smaller,larger = List.partition (fun y -> y<=x) xs
qsort smaller @ [x] @ qsort largerFor example, is a quicksort 'in-place' if your memory gets swapped to disk?
qsort (p:xs) = ...
This is not recommended as it results in worst-case behavior on sorted input lists. (Another commentor correctly pointed out that it requires extra memory for the intermediate lists, too.)Quick sort means nothing to someone who does not yet grok compiling and output, much less sorting as an algorithmic process.
Question isn't whether "hello world" is obsolete, it's the level of knowledge of the author. A rank noob needs to see the simplest possible program, not the highest density functionality.
For a novice programmer learning their first language, they probably don't understand the quicksort algo and probably have no concept of arrays or any data structure. Visually displaying "Hello World" is very simple and teaches you two basic parts of a language: - Syntax - Printing stuff
On another note, someone learning HTML for the first time will have no reason to do quicksort.
But please don't have the audacity of pointing out that original quicksort was supposed to be an efficient in place sort, not a mental exercise in beauty of a language. Then you get a Haskell version that is in place, and supposedly fast. It's about 10 lines longer than the C version, uses Monads, ST, recursion, "unsafeRead/Write", "rscan", "lscan", "swap", "sloop", etc., all together about 20 concepts, built-in functions, etc.
Also, of course, if it really should be fast, you have to use several compiler hints and macros to make it type specialize and all. Obviously.
The C version is shorter, uses nothing but array accesses, do/while, if, int comparisons, and recursion. If you want to explain the C version to a novice programmer, it will maybe take you half a day. The inplace Haskell version? Uhhh, yeah.
I can't help it, but things like these leave me with the impression of Haskell being a theoretically really nice language whose utility in actually getting things done seems somewhat questionable.
Quicksort requires careful selection of pivots, and is unstable. (Many scripting languages (perl, python) are opting for stable sorts)
Check out Bentley&McIllroy's Engineering Quick Sort for a guide about the problems implementing a production ready quicksort.
If you're going to teach them something easy, simple and relatively hard to implement badly, teach them merge sort.
Then teach them adaptive merge sort.
1) how to write a program that guesses a number you thought of by doing binary search.
2) solve 2-queens
3) solve n-queens
4) solve knapsacking or some other combinatorial problem requiring memoization or DP. Of course, I wouldn't tell them any of those buzzwords that are meant to scare them away from just hacking on it.
Their mind will be blown regardless of the language they used and they'll get a feel for O() without even opening Cormen.
Hello World serves two (and only two!) purposes:
1. It's traditional
2. It lets you check everything is working
It isn't a way to evaluate or compare languages. How could it be? It only uses a very small fraction of the language. Note that the Hello World for C is rather long and inelegant. But C itself is definitely an elegant language. So its predictive power is poor.QuickSort is neither traditional nor something a beginning programmer could use to check everything is working. Therefore it is not a substitute for Hello World.
- - -
If you want to get a feel for a language with one code snippet, allow me to introduce the Trabb-Pardo Knuth algorithm:
In their 1977 work "The Early Development of Programming Languages",
Trabb Pardo and Knuth introduced a trivial program which involved
arrays, indexing, mathematical functions, subroutines, I/O,
conditionals and iteration. They then wrote implementations of the
algorithm in several early programming languages to show how such
concepts were expressed.
http://en.wikipedia.org/wiki/Trabb_Pardo%E2%80%93Knuth_algor... ask for 11 numbers to be read into a sequence S
reverse sequence S
for each item in sequence S
do an operation
if result overflows
alert user
else
print resultIt's not like the first thing you're going to do is write out all of quicksort to see if it's easy. You're going to fiddle with numbers an arrays a bit first, particularly if your language has some kind of interactive console. In fact, I wouldn't be surprised if the first thing you do in the language is actually 1+2.
There's quite a bit of syntax you need to learn before quicksort becomes a relevant test.
If you're looking for a good language to build a quick website backend in you probably don't even care about that, you'll care more about having nice ways of passing information around and checking that it has a decent inbuilt sort method.
As far as familiarizing myself with a new language, I usually write a Hello World, then add some variables, and some functions or whatever is relevant, and just focus on the syntax of the language, or in the case of a platform or framework, take a look at building trivial components.
Not a language, but a platform example: I recently explored ExpressJS (If you're not familiar, its a framework for node.js web apps.) and my workflow was: Make a hello world server, Add a few routes and a static handler, Add some views, Add some middleware, Build it into a basic blog. (Because it's always a blog first, right?)
The whole process was quite quick and gave me a very strong jumping point for ExpressJS. Implementing quicksort or something similar as my first crack would probably have been pretty useless. So for me its all about context; I tend to start at Hello World and quickly grow something simple, but relevant to the language or platform.
Trying to come up with a single test that is good turns out to be surprisingly hard. In modern languages I'm looking for the ability to do clean functional code, stateful object code, async programming, a solid module system, and a type system that doesn't get in my way. I really can't imagine a single 5 line program that would encapsulate all of these areas.
Print the words
hello, world
This is a bug hurdle; to leap over it you have to be able to create the program text somewhere, compile it successfully, load it, run it, and find out where your output went. With these mechanical details mastered, everything else is comparatively easy.The C Programming Language [Kernighan, Ritchie]
Gosu's example code does a good job at covering a lot of aspects in ~50 lines of code: