David B. Benson wrote:
I have many ideas for this, of course:
. SML left a lot to be desired as a language and, consequently, all
practical implementations extend the "standard" with extra language
features. SML/NJ adds guarded and or-patterns but MLton does not. MLton
generalizes ad-hoc polymorphism further but SML/NJ cannot. Alice ML adds
platform-independent persistence. And so on.
. SML was insufficient as a tool and, consequently, all practical
implementations extend the "standard" with features like incompatible FFIs.
Writing reliable and up-to-date OpenGL bindings is extremely important and
extremely hard. SML/NJ has its own FFI and its own bindings to some of
OpenGL with few examples. SML# has its own FFI and its own bindings to some
of OpenGL with few examples and so on...
http://www.cs.nyu.edu/leunga/sml-ffi-libs.html
http://www.pllab.riec.tohoku.ac.jp/smlsharp/?Resources%%2FProgramExamples
. The efforts of the tiny SML community were then split across maybe a dozen
incompatible implementations with no clear leader. Meanwhile, the tiny
OCaml community pooled their efforts on a single implementation, making it
develop many times faster than the most popular SML implementation.
. SML/NJ and MLton used to be the most popular SML compilers. SML/NJ took
more market share over the past three years but now it lacks support for
modern (64-bit) machines. There is no clear way forward because there are
now no performant SML compilers (at least for numerics).
. A language needs advocacy and great examples. SML has no vocal advocates
(who is the SML equivalent of me?) and few great examples (where are the
GUI Sudoku solvers and OpenGL-based interactive real-time visualizations?).
. OCaml looks like SML++ because it has lots of extra features with obvious
benefits. The benefits of the parts of SML that are better (e.g. equality
types) are not obvious or easy to explain. People like bells and whistles:
if nothing else, a growing list of features makes a language appear to be
actively developed. Look at my Sudoku solver example, which uses labelled
and optional arguments, guarded patterns and mutable strings:
let rec search ?(x=0) ?(y=0) f accu = match x, y with
9, y -> search ~x:0 ~y:(y+1) f accu
| 0, 9 -> f accu
| x, y when m.(y).[x] <> '0' -> search ~x:(x+1) ~y f accu
| x, y ->
fold (fun accu n ->
let n = Char.chr (n + 48) in
if invalid x y n then accu else
(m.(y).[x] <- n;
let accu = search ~x:(x+1) ~y f accu in
m.(y).[x] <- '0';
accu)) accu 1 10
. Performance: OCaml was put in the lime-light by its excellent performance
on the Great Computer Language Shootout. More recently, OCaml has narrowed
the performance gap to C++ whereas SML has expanded the gap and is now
slower than Haskell on my ray tracer benchmark.
. Brevity: For many simple examples, OCaml is significantly more concise
than SML. (I'm thinking of things like camlp4 parsers rather than the "end"
keyword, BTW). Look at this trivial calculator example that reuses OCaml's
lexer and defines its own LL parser using camlp4's elegant little syntax:
open Camlp4.PreCast
let expr = Gram.Entry.mk "expr"
EXTEND Gram
expr:
[ "sum" LEFTA
[ e1 = expr; "+"; e2 = expr -> e1 +. e2
| e1 = expr; "-"; e2 = expr -> e1 -. e2 ]
| "product" LEFTA
[ e1 = expr; "*"; e2 = expr -> e1 *. e2
| e1 = expr; "/"; e2 = expr -> e1 /. e2 ]
| "power" LEFTA
[ e1 = expr; "^"; e2 = expr -> e1 ** e2 ]
| "simple" NONA
[ n = INT -> float_of_string n
| x = FLOAT -> float_of_string x
| "("; e = expr; ")" -> e ] ];
END
let () =
while true do
Printf.printf "> %%!";
let stream = Stream.of_string (input_line stdin) in
let x = Gram.parse expr Loc.ghost stream in
Printf.printf "= %%f\n%%!" x;
done
. Many people (like me) were taught SML at university in a way that gave it
a stigma of being impractical. Take for example the bloody n-queens
problem, which is perhaps the worst possible example to use if you want any
hope of building a userbase because it is such an utterly pointless
academic exercise. There are more implementations of the queens problem
listed for SML than there are for OCaml according to Google:
sml "queens problem": 314
ocaml "queens problem": 311
Contrast with "OpenGL" or "GUI" where OCaml gets 3-4x as many hits:
sml opengl: 303,000
ocaml opengl: 1,230,000
sml gui: 563,000
ocaml gui: 1,750,000
IMHO, the moral of the story is: if you want your language to become popular
then work as a team to build something of practical value with great
examples and keep developing it. You must write basic library bindings
(GTK, OpenGL and maybe even Apache) and you must build a decent development
environment (type throwback, integrated build system and maybe even
typesetting). I believe the ability to commercialize software (even on the
Linux platform) will become increasingly important in coming years. OCaml
is particularly weak at this but a new language could offer the ability to
buy, download and JIT compile platform independent applets using standard
APIs for GUIs (GTK?), graphics (OpenGL) and so on. If such a language had
packages for all of the major distros then this would completely remove the
currently prohibitive problem of incompatible binary DLLs and so forth.
If there is one thing I have learned from industry it is "every problem is
an opportunity". The SML community have some awesome pioneers among them
(Matthias Blume, Matthew Fluet, Stephen Weeks, Alan Mycroft, Torben
Mogensen...) and the time is ripe to learn from previous mistakes and
leapfrog OCaml. I am quite sure that it is possible to create a better
language with a better implementation. If anyone did this, I would surely
get on-board!
Finally, I would like to note that my interpretation of "popularity" is
atypical. I am less interested in a userbase of web programming
script-kiddies and much more interested in the fact that OCaml is now
widely used in scientific computing and, in particular, many of the world's
leading bioinformatics institutes. So being popular is not just about
topping a chart and being trendy, it is also about saving lives.