When we write human languages (that use a Latin script), we use punctuation to delineate the beginning and end of terms. In a language like C or Rust, terms are surrounded by commas, parentheses, angle brackets, and so on. In OCaml and Haskell, many things that there is syntax for in C-style languages are done as ordinary function calls, which separate terms by only whitespace.
It is easier to read this (Rust):
let value = some_long_ass_function_name(some_quirky_parameter, another_one);
another_function(value)
than this (Haskell): let value = someLongAssFunctionName someQuirkyParameter anotherOne
in anotherFunction value
or this (OCaml): let value = some_long_ass_function_name some_quirky_parameter another_one in
another_function value
Individual terms in camel case are difficult to read if they consist of more than a couple words. Consecutive terms in snake case are difficult to read because underscores and whitespace look alike visually.Haskell and OCaml's idiomatic solution is to use extremely terse names for arguments, type variables, and local variables, out of what seems to be syntactic necessity.
someLongAssFunctionName someQuirkyParameter
And we get a function that accepts one parameter. But in Rust you would have to do this: move |another_one: i32| {
some_long_ass_function_name(some_quirky_parameter, another_one)
}
Which is not easier to read. some_long_ass_function_name(some_quirky_parameter, ..)
which would be more readable without giving up on punctuation. func(param1, _)
Every once in a while you have to make some change to that expression. // you may want to write
func(param1, func2(_))
// but you need to write the full lambda
param2 => func(param1, func2(param2))Of course, I haven’t read every file, so maybe I got lucky with my random sampling.
Excerpt:
> Tradition dictates that Unix system programming must be done in C. For this course we found it more interesting to use a higher-level language, namely OCaml, to explain the fundamentals of Unix system programming.
> The OCaml interface to Unix system calls is more abstract. Instead of encoding everything in terms of integers and bit fields as in C, OCaml uses the whole power of the ML type system to clearly represent the arguments and return values of system calls. Hence, it becomes easier to explain the semantics of the calls instead of losing oneself explaining how the arguments and the results have to be en/decoded. (See, for example, the presentation of the system call wait, page ??.)
> Furthermore, due to the static type system and the clarity of its primitives, it is safer to program in OCaml than in C. The experienced C programmer may see these benefits as useless luxury, however they are crucial for the inexperienced audience of this course.
> A second goal of this exposition of system programming is to show OCaml performing in a domain out of its usual applications in theorem proving, compilation and symbolic computation. The outcome of the experiment is rather positive, thanks to OCaml’s solid imperative kernel and its other novel aspects like parametric polymorphism, higher-order functions and exceptions. It also shows that instead of applicative and imperative programming being mutually exclusive, their combination makes it possible to integrate in the same program complex symbolic computations and a good interface with the operating system.
Related: https://willamette.edu/~fruehr/haskell/evolution.html