3 ms·
Only somewhat related,but I've tried to learn ocaml before but have never been able to figure out when to put what kind of delimiters where. Can anyone recommen
by tntn 8y ago
Only somewhat related,but I've tried to learn ocaml before but have never been able to figure out when to put what kind of delimiters where. Can anyone recommend a resource that explains the usage of the double comma and the like?
- laylomo2 8y agoThe double semicolon only matters in the REPL (aka the "toplevel"). Off the top of my head, I can think of at least two other situations where punctuation matters: 1) Whenever you have nested match cases: match left with | Some left -> match right with | Some right -> Some (left, right) | None -> None | None -> None The compiler does not use indentation to figure out scoping, so the above gets treated as: match left with | Some left -> match right with | Some right -> Some (left, right) | None -> None | None -> None So you need to surround the inner match with parens match left with | Some left -> ( match right with | Some right -> Some (left, right) | None -> None ) | None -> None 2) If you are doing imperative things inside an if statement: Consider the following function: let cache_file file = if not (file_exists file) then printf "downloading file\n"; download file else printf "file already exists\n" The problem here is that OCaml allows one to create an if statement with no else clause. And since the compiler doesn't use indentation to figure out scoping, then the code is essentially treated like the following: let cache_file file = (if not (file_exists file) then printf "downloading file\n"); download file; else (printf "file already exists\n"); Which is just totally wrong. So in order to do multiple imperative actions within an if block, you should use either parens, or begin/end delimiters (which are treated exactly the same as parens) let cache_file file = if not (file_exists file) then begin printf "downloading file\n"; download file end else printf "file already exists\n"
- dpwm 8y agoThere's an interesting thing with the semicolon. I've heard people advocating thinking of the semicolon as a binary operator: (;) : unit -> unit -> unit Of course, the reality is more complicated than this, because it can be used at the end of an expression, where it behaves like a postfix operator of type 'a -> 'a. Let's take your example: match left with | Some left -> match right with | Some right -> Some (left, right) | None -> None | None -> None you can actually do match left with | Some left -> match right with | Some right -> Some (left, right) | None -> None ; ; (* <-- two separate semicolons *) | None -> None This doesn't just work for imperative stuff, like the operator theory of the semicolon, it will work with this example. My understanding is that this is due to the fact that optional semicolons are allowed at the end of statements and close the current expression. So we're closing the first expression (None) and then closing the second expression (the inner match). The double semicolon is something else altogether. Though it is worth noting that this example is straying from idiomatic OCaml and we can avoid this altogether with better matching: match (left, right) with | (Some left, Some right) -> Some (left, right) | _ -> None Both the native optimizing compiler and BuckleScript are able to do what you would expect with this: the matched tuple is optimized away. Your second unfixed example actually causes a syntax error. There is an if expression in OCaml and an if statement. This is particularly unfortunate, because the let cache_file = function | file when file_exists file -> printf "downloading file\n"; download file | _ -> printf "file already exists\n" first semicolon within an if expression turns the whole thing into an if statement, and an if statement can have no else clause. The else clause is then without an if statement, because we've triggered the imperative if statement. This is a syntax error. were we to define an operator let (>>>) a b = a; b then we could replace that semicolon with an >>> and things behave as expected. But it's really that if can be both a statement and an expression. For this reason I prefer using matches in general. let cache_file = function | file when not (file_exists file) -> printf "downloading file\n"; download file | _ -> printf "file already exists\n"
- theaeolist 8y agoOCaml has no guaranteed order of evaluation, which is not what you want with (;). It needs to be part of the language as special syntax.
- LeonidasXIV 8y agoThe signature of `;` where it an operator is more like (;) : unit -> 'a -> 'a And you can see it as a kind of sequencing operator, since it returns the value of the right hand side unchanged.
- thedufer 8y agoI can't think of any time a double-comma would be syntactically correct. Double-semicolons, which may be what you're referring to, are never required (although in some situations they will cause syntax errors to appear closer to the actual problem). They can be placed after all top-level value bindings. Probably your best bet is to follow an intro series so you see some examples (https://dev.realworldocaml.org/ https://dev.realworldocaml.org/ is the best at the moment, I believe), although if you're so inclined you could just read the BNF for the language (https://caml.inria.fr/pub/docs/manual-ocaml/language.html https://caml.inria.fr/pub/docs/manual-ocaml/language.html).
- richeyryan 8y agoNot a direct answer to your question but you could look at Reason. It is a C style syntax that layers on top of the OCaml semantics. Writing in Reason is writing OCaml. However, the new syntax makes it more approachable for people coming from C style languages and removes idiosyncrasies like the double semicolon. Its still progressing and more focus has been given to getting it up and running in a compile to JS context but it should be equally as capable of systems work, especially as time goes on.