Mostly Software

July 23, 2007

Why O’Caml is not my favorite programming language

Filed under: Software — Tags: , , — schani @ 9:42 pm

A few hours ago the ICFP Programming Contest 2007 ended, and the team Funktion im Kopf der Mensch participated again, this year slightly demotivated by the fact that the organizer’s main goal seems to have been to show off how smart they are instead of letting the participant practice their creative skills.

As always we were using Objective Caml for most of our programming work. O’Caml has always had some annoying sides, but this year I ran into so many of them that I got seriously pissed off, and will now have to investigate other options.

For us, O’Caml’s main attraction are its type system, which, when used correctly, makes it surprisingly hard to write incorrect code, and its performance. O’Caml’s big weakness is its standard library. To be frank, it sucks, big time.

I’ll present the issues I ran into during the past three days, and I’ll compare the way O’Caml handles those things with Common Lisp, because in the areas I’ll discuss here, it is a good example of how to do it right. Note that I’m not saying that Common Lisp does everything else better. There is a reason why we’ve been using O’Caml, after all.

Let’s start with numbers. Say we need a function which adds the number 3 to a given number. Should be a trivial task, right? Indeed, in Lisp it is:

(defun add-3 (x)
  (+ x 3))

Let’s see if it works:

[2]> (add-3 0)
3
[3]> (add-3 4.5)
7.5
[4]> (add-3 3/2)
9/2
[6]> (add-3 (sqrt -4))
#C(3 2)

Great – we can give the function any kind of number, and it adds 3. How do we implement this in O’Caml? Well, first we’ll have to decide which kind of number we want to operate on, because, you see, you can’t mix different kinds of numbers. Ok, let’s concentrate on integers. There can’t be more than one kind of them, can there? Well, it turns out there are several. There’s “int”, “int32″, “int64″, “nativeint” and “big_int”. Here’s the code for all of them:

let add_3_int x =
  x + 3
let add_3_int32 x =
  Int32.add x (Int32.of_int 3)
let add_3_int64 x =
  Int64.add x (Int64.of_int 3)
let add_3_nativeint x =
  Nativeint.add x (Nativeint.of_int 3)
let add_3_big_int x =
  add_big_int x (big_int_of_int 3)

And those are just for the integer types! How ridiculous can it get?

Next issue: Arrays. Let’s say we need a function which returns an array with all the elements of the array it was given in reverse order, except for the last one. A triviality in Lisp:

(defun chop-rev (seq)
  (reverse (subseq seq 0 (1- (length seq)))))

Let’s see if it works:

[10]> (chop-rev #("abc" "123" "xyz"))
#("123" "abc")
[9]> (chop-rev "abcdef")
"edcba"

Notice that in Lisp string are arrays, too. As an added bonus, our function even works on lists:

[8]> (chop-rev '(1 2 3 4))
(3 2 1)

What can O’Caml do for us? Again, we first need to ask: Which kind of arrays are we talking about? There’s the built-in array type “array”. Then there’s strings, which O’Caml doesn’t treat as arrays, for no apparent reason. There’s another type called “Buffer”, which is really just a string that can grow, but is, of course, completely incompatible with “real” strings. There’s also something called “bigarray”, which is an array that can be big. In any other language such a data structure would be obsolete, because standard arrays wouldn’t have any size limits. Not so in O’Caml! You can enjoy all the comforts of the built in array type, but only if you don’t need to put in more than about 4 million elements (on 32 bit systems), unless you work with floats, in which case you’re limited to 2 million elements. Perhaps I should also mention that strings are limited to 16 million characters, but they forgot to implement big strings. What a joy!

About these ads

25 Comments

  1. I don’t want to defend OCaml too much, but your examples are bad ones: there are easy ways of expressing Lisp-like numbers and lists in OCaml. But, in the end, both OCaml and Lisp are obsolete. If you want an easy-to-use dynamic programming language, there are plenty better choices than Lisp, and for static type systems, people have made a lot of progress over the last decade.

    Comment by Mike — July 23, 2007 @ 11:07 pm

  2. Have you tried Haskell yet? I (unfortunately) don’t use enough functional languages day to day, but I’ve heard a lot of good things about Haskell…

    Comment by Max Battcher — July 24, 2007 @ 12:41 am

  3. Wow. I have no idea what that means.

    I couldn’t resist stopping by when your blog title is so intriguing.

    Enjoy your day.

    Comment by Bob — July 24, 2007 @ 4:42 am

  4. Mike: There is no easy way (indeed I claim that there is no way) to express Lisp-like integers (Lisp also provides rational, floating point and complex arithmetic) in O’Caml so that they behave like standard integers, i.e. without conversion to and from standard integers when interacting with standard O’Caml functions.

    Also, I wasn’t talking about lists (you can’t express Lisp-like lists in O’Caml because they can’t be statically typed), but about arrays. And yes, you can use big arrays, and I suppose they work, but then why provide the “small” array type at all? Why can’t all arrays be big?

    My point isn’t that can’t implement those basic features in O’Caml, my point is that they are not implemented in the standard library. Why not?

    As for dynamic languages better than Lisp: Could you give some examples?

    Comment by schani — July 24, 2007 @ 7:40 am

  5. My friends and I (3 of us) did the ICFP contest this weekend and decided to learn Ocaml as part of it. We hit up against many similar issues, and didn’t even get the dna to rna converter working completely, but we did learn a lot. Ocaml’s standard libraries suck, but if you augment them with Extlib and Bigarray, you can get a lot of benefit. We ran into the limits on the string sizes, and have had to move the code over to using a Bigarray of chars…

    Eventually, I’ll post about the experience =)

    -Dave

    Comment by David Hogarty — July 24, 2007 @ 8:38 am

  6. add3 :: (Num a) => a -> a
    add3 x = x + 3
    chop_rev seq = drop 1 (reverse seq)

    Implements the same functions in Haskell.
    It seems much less annoying than O’Caml, but probably has its own quirks.

    *Main> add3 0
    3
    *Main> add3 4.5
    7.5
    *Main> chop_rev [1, 2, 3, 4]
    [3,2,1]
    *Main> chop_rev “abcdef”
    “edcba”
    *Main> chop_rev ["abc", "123", "xyz"]
    ["123","abc"]

    Comment by Anders — July 24, 2007 @ 9:10 am

  7. There was a lot of success on the part of the Haskell people this year — we had implementations topping 40k iterations per second. A lot of this was down to library support, especially the recently became available ByteString library. As you probably are aware, type classes in Haskell pretty neatly solve the issues that you mention (though many people wish that the standard numeric hierarchy conforms to the mathematical one a bit more).

    Comment by Gen Zhang — July 24, 2007 @ 9:11 am

  8. I’m aware that Haskell is much better in the areas I’ve had issued with in O’Caml, and I’ll certainly give it a try in the near future.

    Thanks for the example, Anders!

    Comment by schani — July 24, 2007 @ 9:22 am

  9. And the thing with Haskell is that there’s often an even terser way to do it.

    add3 :: Num a => a -> a
    add3 = (+) 3

    chop_rev = drop 1 . reverse

    Comment by Per Melin — July 24, 2007 @ 12:13 pm

  10. And to prove my own point:

    chop_rev = tail . reverse

    Comment by Per Melin — July 24, 2007 @ 12:21 pm

  11. I concur with your criticism (both with ocaml and this year’s contest).

    Unfortunately, the show-off attitude of the contest organizers got me really disheartened. As a member of your team I feel this is the right time to say “I’m sorry. I didn’t want to let you down.” By-gone.

    These ocaml issues you listed (plus a few more, like generic parsers/printers, 31-bit integers, and missing stdlib functionality in general) really bother me.

    For some of these problems there is a quick, decent fix. Generic parsers/printers can be done by using camlp4, like Markus Mottl did with his sexplib.

    Other issues have no simple solution. The ocaml stdlib remains very stable (and feature-poor) over the years, so developers are forced to write (test, and debug) their own stdlib-replacement/addendum.

    The most serious problem I see with ocaml, however, is that the compiler discourages you to write compact, elegant code (that uses separate modules and higher-order functions). If you are heading for good performance, you end up writing lots of code that does not use these features.

    People that use ocaml in real life seem to bump into these problems regularly, as can be seen in the article “Caml trading: Experiences in Functional Programming on Wall Street” in “The Monad Reader” by Yaron Minsky.

    Maybe Haskell is a better overall choice than ocaml indeed. Thanks to the negative experiences of this weekend, I am now seriously considering moving to Haskell, too.

    Comment by skral — July 24, 2007 @ 1:11 pm

  12. performace is no excuse for a bad language. and a bad language is no excuse for performance.
    unless its a performance critical application (and REAL critical), i can’t see how O’Caml can be better than Common Lisp.

    Comment by diogo — July 24, 2007 @ 4:52 pm

  13. I used the recently released Vec library (http://www.dealfaro.com/home/vec.html) for the contest and it worked perfectly. Not having type classes or some other way to have polymorphic operators is definitely annoying… at one point I understood their motivation but lately I’ve been eyeing Haskell like many others :)

    Comment by Brock — July 24, 2007 @ 6:43 pm

  14. [...] Why O’Caml is not my favorite programming language A few hours ago the ICFP Programming Contest 2007 ended, and the team Funktion im Kopf der Mensch participated again, […] [...]

    Pingback by Top Posts « WordPress.com — July 24, 2007 @ 11:59 pm

  15. > Mike says : both OCaml and Lisp are obsolete

    I don’t think LISP is obsolete. :)

    Comment by Nelson Castillo — July 25, 2007 @ 9:22 pm

  16. I have used F# (OCaml’s dialect from Don Syme at MS Research) for ICFP 2007. It was my first F# program also :) and i had just Fri and part of Sat for fun :(. My entire dna decoder and rna->image translator is about 450 LOC and i’ve image self test passed. From my Lisper/Schemer point, F# is nice mental practice and it’s definitly not a dark side of power :)

    Comment by ssp — July 26, 2007 @ 4:32 pm

  17. F#’s pretty cool. It’s like Ocaml, but with a much bigger class library. Performance is similar to Ocaml, and you can use it on Mac or Linux if you install the “Mono” version of the CLR.

    And there’s no annoying “arrays can only be this big” limits, because the CLR memory system doesn’t store type tags in pointers.

    …I think this year’s IFCP was very difficult. They should have had more conformance tests to help out teams with buggy implementations.

    Comment by Joe web surfer — July 28, 2007 @ 12:58 am

  18. The language your looking for is Haskell. Haskells type classes make writing the kind of polymorphic functions your looking for easy and unlike lisp your not giving up on type safety.

    Comment by David — July 28, 2007 @ 2:08 pm

  19. There are many different numeric types, such as modulo ints, integers, arbitrary-precision rationals, floating point numbers, arbitrary-precision floats, intervals and so on. I notice that all of your examples happen to use only the numeric types that are bundled with Lisp.

    I wonder how your examples would compare if you looked at numeric types that don’t happen to be bundled with Lisp? Interval arithmetic is far more useful than arbitrary-precision rationals, for example…

    Comment by Jon Harrop — July 31, 2007 @ 12:20 pm

  20. I see the well known caml (and F#) troll harrop
    found his way here. It sure doesn’t feel right that
    all these people became disillusioned with ocaml
    does it John ? Less potential vcustomers (= suckers) for you.
    Jumping ship to Haskell must hurt through.
    Oh the irony ;-)

    Comment by Nick — September 7, 2007 @ 3:32 am

  21. Functional languages confuse the hell out of me. I’d much rather stick with ym high level C++ and Java then get down and dirty with things like Caml, Haskell and Scheme..

    Comment by David — March 7, 2008 @ 11:48 pm

  22. Let’s have a functional language programming contest :)

    Comment by Programming Contest — May 25, 2008 @ 2:45 pm

  23. >>Functional languages confuse the hell out of me. Iā€™d much rather stick with ym high level C++ and Java then get down and dirty with things like Caml, Haskell and Scheme.
    I really hope you realize what you just wrote.
    C++ and Java Hight-Level Language…riiight..
    To Original Poster:Your Whole post doesn’t make the least bit of sense to be honest.And stop being a speed kiddie for god sake,learn how to think and solve problems.

    Comment by doesitmatter — September 10, 2008 @ 10:01 pm

  24. I have a bunch of open source source code written in Ocaml.

    I would like to know if there is a way to convert these Ocaml source code files to C/C++ or PHP.

    Why?

    Well, I don’t want to learn a new language program. I have enough with the fact that I have to program in C/C++, C#, Visual Basic, PHP, ASP, Javascript, ActionScript. Learning a new language is tedious.

    Please, If you know a program that would make me some nice C files from the Ocaml files (.ml) let me know. Send me an email to axllaruse@yahoo.com

    Thanks

    Comment by axllaruse — October 3, 2008 @ 2:54 am

  25. The language isn’t Irish: its name is OCaml, not O’Caml :-)

    Comment by mr. kleen — January 20, 2009 @ 8:59 pm


RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

The Shocking Blue Green Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: