Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm curious about what you find particularly confusing about OCaml. I'm a (relative) newcomer to the language, but I find it extremely readable, even if it's a bit clunky at times.


Good OCaml code is one of most readable in the category of static languages, I agree. But it's less "writable" than readable in my opinion. Of course you can get used to the syntax, but for me expressiveness and clarity of comprehension comes from both: simplicity of writing and reading.

Often I feel like there is a barrier between your thoughts and their execution which does not exist in Python or Ruby for example. When I switch from OCaml to Python it's like a breath of fresh air.

In conclusion I think common tasks must be syntactically abstractable. For example, I find working with standard data structures in OCaml annoying, as if I were programming in C. There are tons of syntax extensions for OCaml that try to fix these defects, but it only supports my claims.


Learning Python was certainly easier for me. I could really hit the ground running. OCaml had a much steeper learning curve. It took me a while to get used to the compiler and the different style of programming.

However, I'm a professional. Some of the powerful tools I use take a serious investment to learn. Here it paid off well.

Now I find that Python programs are easy to start but OCaml programs are easy to finish. The compiler is an invaluable helper that I miss when using other languages. Some syntax is clunkier than others but to me having good types (and a good compiler) makes or breaks a language. I can get my work done in anything but this is an area where the language really helps me out.


What does this code do?

  if a > 0 then
    print_endline "a > 0" ;
    match a with
      | 0 -> print_endline "impossible"
      | 2 ->
        match b with
          | 0 -> print_endline "2, 0"
          | _ -> print_endline "2, not 0"
      | 3 -> print_endline "3, something"
      | _ -> print_endline "something, something"
  ;
  print_endline "done"


Any decent programming editor will be able to indent that properly and you will see the problem. Also, I agree that it is a bit ugly but it's not that complicated to understand how the match syntax works. Adding a "begin" and an "end" in this code is simple enough :).


It's not just the match syntax; it's also the `;` expression separator.

> Any decent programming editor will be able to indent that properly and you will see the problem.

This seems like a weak excuse. In particular, I could turn it around and say, "any decent programming language should be writable without an editor". Also, the issue isn't just reading, it's writing too - it's much harder to foresee/plan all the `begin`/`end`, while you're writing a line of code, that will make the lines that follow work as intended.


> This seems like a weak excuse. (…)

Fair enough, but for the ';', as others explained meanwhile, I think it's pretty simple to understand, it's just that we are not used to it because of C syntax.

EDIT: actually, you are right about ';', it is confusing when I think about it: it does not have the same behavior in a branch of a `match` and in the branch of an `if`… I wonder how I never had problem with that before.


It depends on the learning path of each one.

In the Pascal family of languages, ';' is a separator as well.


OCaml will give you compiler warnings on the incomplete and redundant match cases. F# will silently execute a semantically different version of your code. I prefer OCaml. Indentation sensitivity was one of F#'s design flaws.


As someone without too much OCaml experience, how do you disambiguate this?


1) Ignore indentation (I intentionally wrote it to deceive, but similar examples could easily appear in real code). 2) `match` cases always bind to the innermost `match` statement. 3) Statement separators (`;`) are tricky.

The correct indentation of the above code is:

  if a > 0 then
    print_endline "a > 0" ;
  match a with
    | 0 -> print_endline "impossible"
    | 2 ->
      match b with
        | 0 -> print_endline "2, 0"
        | _ -> print_endline "2, not 0"
        | 3 -> print_endline "3, something"
        | _ -> print_endline "something, something"
            ;
            print_endline "done"
To have the same meaning as the indentation implies, you would need to add `(...)` or `begin ... end` at the appropriate places.


What would be the corresponding SML? I see how the way SML binds ';' would help here, but would it change anything about the last two badly indented matching? And it seems to provide you with the equivalent footgun if you attempt to do multiple side-effect operations in a match branch, which in my experience you want to do more often than you need to separate matches with ';'.


[deleted]


Not in my version of OCaml (OCamlWinPlus v1.9RC4, OCaml version 4.01.0):

  # if false then print_endline "false" ; match () with () -> print_endline "match";;
  match
  - : unit = ()


Sorry I realized my mistake and deleted my comment before I saw yours.

FTR, I was saying that the ";" in the `then` clause of the if statement didn't end it, but it actually does. I see that arjunnarayan got this wrong too in his comment here: https://news.ycombinator.com/item?id=8498187.


I figured the indentation was a lie, but didn't realize you would have to introduce something like begin...end to make it work the way it appears.


There are two things to remember. The first is the match binding thing that tomp mentions in his reply.

The second one is that in OCaml, semicolon is a separator, and not a terminator. In contrast, in C/C++, semicolon is a terminator. If you have an expression, you end it with a ";" just because.

This is not the case for OCaml. In OCaml, semicolon is used to separate two sequential expressions where only one expression is expected. Thus,

    <expr1>;<expr2> 
is evaluated in sequence, and can be used in a place where only one is expected. For example, if statements have the following syntax:

    if <expr1> then <expr2> else <expr3>
Now if you wanted to do two things (instead of one) in the "then" block, you would simply write

    if <expr1> then <expr2.1>;<expr2.2> else <expr3>
Notice that under these rules

    if <expr1> then <expr2>; else <expr3> 
makes no sense. Separators are not terminators. We are used to thinking of ";" as terminators because of C/C++.


    if <expr1> then <expr2.1>;<expr2.2> else <expr3>
Actually, this will not work, I was also confused by it.

    # if true then (); 1 else 2;;
    Error: Parse error: [str_item] or ";;" expected (in [top_phrase])
    # if true then begin (); 1 end else 2;;
    - : int = 1
    # if true then ((); 1) else 2;;
    - : int = 1
The confusion comes from the fact that it doesn't behave the same way in match expressions:

    # match true with | true -> (); 1 | false -> 2;;
    - : int = 1


I'll add that you need ';'-as-separator (you also use ';' in other places, such as when separating items in a list) only when calling functions which return 'unit', which is typically functions which perform side-effects (eg, close a file). That's usually a small portion of your program.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: