[HN Gopher] OCaml at First Glance
       ___________________________________________________________________
        
       OCaml at First Glance
        
       Author : todsacerdoti
       Score  : 232 points
       Date   : 2022-08-29 11:00 UTC (12 hours ago)
        
 (HTM) web link (batsov.com)
 (TXT) w3m dump (batsov.com)
        
       | JassicaB4 wrote:
        
       | nerdponx wrote:
       | This pretty much squares with my experience as well. I also want
       | to shout out CS3110 as being an excellent (free!!) learning
       | resource, and that having both a well-written textbook with
       | exercises and short accompanying video lectures is a wonderful
       | combination. I will never not be amazed at and grateful for high-
       | quality university learning material like this being made freely
       | available.
        
         | acka wrote:
         | For those who are interested in the CS3110 textbook and don't
         | like Google sending them wristwatch shopping instead, here is a
         | link to the textbook{1].
         | 
         | [1] https://cs3110.github.io/textbook/
        
           | a-nikolaev wrote:
           | Just to add to this, I wrote additional lecture notes for the
           | class on OCaml I taught, which was largely based on this
           | book.
           | 
           | http://a-nikolaev.github.io/fp/ - if anyone is interested in
           | more learning resources.
        
       | gavinray wrote:
       | I really want to like OCaml, as a more practical Haskell, but the
       | syntax to me is just weird.
       | 
       | I think the ReasonML/ReScript guys had the right idea tbh, but
       | I'm not interested in writing JS with it.
        
         | donut2d wrote:
         | You can actually compile ReasonML to native code with dune.
         | 
         | What are some of the things that weird you out about OCaml's
         | syntax?
        
           | gavinray wrote:
           | > You can actually compile ReasonML to native code with dune.
           | 
           | Yeah but the community doing native ReasonML is small and the
           | maintenance has really petered off.
           | 
           | With OCaml 5 looming you're better off just biting the bullet
           | and writing OCaml if you're going to do it IMO.
           | > What are some of the things that weird you out about
           | OCaml's syntax?
           | 
           | For whatever reason, I really dislike the named-argument
           | syntax -- and some of the operators make it hard to read
           | compared to named alternatives IMO.
           | 
           | Below examples showcases some of these:                   let
           | variables = (json_variables :> (string *
           | Graphql_parser.const_value) list)              ~resolve:(fun
           | info () ->           Lwt_result.ok (Lwt_unix.sleep duration
           | >|= fun () -> duration)         )
        
       | AzzieElbab wrote:
       | I had a very brief experience with OCaml debugging some seriously
       | complicated networking code. Putting aside the quirkiness of the
       | language, its compiler is a wonder of the world. It is
       | practically as fast as GO which is a miracle given how much more
       | sophisticated OCaml is.
        
       | yodsanklai wrote:
       | I'm surprised people care about the syntax... that's pretty much
       | the least important part of the language.
       | 
       | I've got a few issues with OCaml
       | 
       | 1. The standard library is inconsistent. Different projects use
       | different alternatives and it's annoying to switch between then.
       | 
       | 2. Concurrency using Lwt/Async. Monads feel more ad-hoc in OCaml
       | than Haskell because there's no type classes and again no
       | consensus on how it should be done. Some projects use tons of
       | variation of `>>=`, other use `let%bind`. Again, no clear
       | consensus and reliance on external libraries which aren't always
       | well documented. I find code relying too much on monads to be
       | much less elegant and simple that plain OCaml.
       | 
       | 3. "includes". I tend to get lost in codebase which abuse
       | includes.
       | 
       | 4. It's a small community. If you want to work on "real world"
       | stuff, most likely you will stumble into tooling/libraries
       | issues. Not all of these things are very mature or documented and
       | they're evolving fast.
       | 
       | I'm wondering if F# suffers from the same issues.
        
         | momentoftop wrote:
         | > Some projects use tons of variation of `>>=`, other use
         | `let%bind`
         | 
         | It gets better. Since 4.08, the preference would be `let*`.
        
         | daxfohl wrote:
         | As others have said, F# addresses these issues. The main
         | complaint I have with F# is when using other dotnet libraries
         | you end up having to deal with things like nulls again, which
         | can make the F# feel more cumbersome than it should be. I still
         | like it though.
        
           | pjmlp wrote:
           | My main complaint is that after all these years, Microsoft's
           | management still seems not to have a clear picture what they
           | want it for, althought it seems to have replaced Visual Basic
           | in feature love for newer .NET versions.
        
             | daxfohl wrote:
             | I worked in Azure for four years in a couple different
             | teams. I didn't see a single line of F# code while I was
             | there. I don't think they have any plan beyond supporting
             | it as somebody's side project.
             | 
             | Edit: I forgot about https://github.com/microsoft/qsharp-
             | compiler. IDK if any server code is in F#, but at least the
             | compiler is.
        
         | hvs wrote:
         | F# has the entire .NET library available, so that won't be an
         | issue.
        
           | oaiey wrote:
           | I was surprised that the article mentions dozen of languages
           | but no word of F# which is a mainstream clone/derivate of
           | OCaml. Especially considering exactly that point.
        
             | lf-non wrote:
             | I think that's understandable.
             | 
             | Those dozens of the languages are the ones that the author
             | has personally dabbled with in the past. The focus of
             | article is their personal experience & first impressions.
             | 
             | It was not intended to be an exploration of what else is
             | available in the market and how ocaml compares to them.
        
         | adelarsq wrote:
         | 1. For F# you can can use both .NET and JavaScript libraries
         | (with tool called Fable), so isn't a issue.
         | 
         | 2. There a lot of ways to the that, which one with pros and
         | cons, but isn't a issue in my opinion
         | 
         | 3. For imports there are a thing called AutoOpen that is
         | strange at first. Just need to be carefull where to use
         | 
         | 4. .NET documentation tend to be writed for C#. So you need to
         | understand at least a little of C# if you want to use that
         | libraries. But also there are a lot that can be use
         | idiomaticaly with F#, so isn't a big issue.
        
         | freedomben wrote:
         | > _I 'm surprised people care about the syntax... that's pretty
         | much the least important part of the language._
         | 
         | Eh, I don't think I can agree. There are definitely more
         | important things about a language than syntax, but a language
         | with a great syntax can be a lot more enjoyable to use,
         | particularly when reading a lot of code. Prior to learning Ruby
         | I would have agreed with you, but since Ruby and Elixir, the
         | syntax adds much to my enjoyment of working with the language.
         | When I think of ES7 v. ES5 I feel the same way as well. You can
         | do everything in ES5, but in ES7 the syntactical sugar makes it
         | so much more enjoyable.
        
           | phist_mcgee wrote:
           | I've found newbie JS devs do confuse the meanings of `=>` and
           | `function` to mean the same thing in JS and think that it's
           | just a sugar. I wonder if there's a nice way to 'unfold'
           | sugars via a linter or something to explain in code the
           | subtleties.
        
           | bmitc wrote:
           | Interesting, because I find Elixir's syntax to be rather
           | busy, especially coming to it from F#. I love Elixir and
           | Erlang, but Ruby's influence on Elixir is probably my least
           | favorite thing about Elixir.
        
         | mattpallissard wrote:
         | I think your comment is the most accurate depiction of the
         | warts.
         | 
         | Yeah, the standard library is inconsistent, and they don't seem
         | keen to merge in some features when they're readily available
         | in other libraries. Plus there are some odd implementation
         | details in the Unix module (for example, read/write and
         | friends) at the C level that don't seem to get much traction on
         | fixing despite fairly clear paths to resolution.
         | 
         | I personally don't care about the difference between binding
         | something to a variable and the infix operator.
         | 
         | What I don't like are the multiple concurrency stories, this is
         | similar to the problem seen with the standard library vs
         | janestreet's. Although with the module system being what it is
         | it's usually not too big a deal to support either concurrency
         | library (even though some libraries force you to use one or the
         | other).
         | 
         | Although I'm hopeful that with multicore finally being a real
         | thing, the community will settle on a single concurrency
         | library that can be pulled into the standard library in the
         | future.
         | 
         | Despite the issues, it is still my favorite language.
        
         | devmunchies wrote:
         | syntax doesn't typically matter as long as you are at least as
         | productive as in other languages. i.e. if editors can do the
         | same things with keybindings.
         | 
         | The problem with the (* *) comments is that I can select a
         | block of text, a portion of which is already commented out, and
         | commented the whole selection. You can't solve this without
         | lossy commenting (e.g. removing the inner comment). The portion
         | that is already commented will screw it up. This doesn't matter
         | in single line comments since it will just add an additional
         | "//" in front of a commented line.
        
           | pie_flavor wrote:
           | Does OCaml not have nested comments? Typically a language
           | supporting /* */ will treat them like parentheses and require
           | each opener to match a closer. (Not that this doesn't make
           | documenting the behavior of files/static/* harder - hence
           | Rust and C# preferring to document with line comments.)
        
             | octachron wrote:
             | OCaml has nested comments (and comments are also aware of
             | string literals). Thus any fragments of valid OCaml code
             | can be commented without changes. In other words, the whole
             | line below is commented-out.                    (* let x =
             | "*)" (* inner comment *)  *)
        
             | folmar wrote:
             | > Typically a language supporting /* */ will treat them
             | like parentheses
             | 
             | This is not the case for C, C++ or JavaScript for a start.
        
         | 0x457 wrote:
         | Syntax is what you deal with every time you read or write in
         | any language. It can't be "the least important". It's probably
         | one of the most important part when you _read_ the code, and
         | reading the code is an important part of programming.
         | 
         | Just take a look at this:                   [1, 2; 3, 4]
         | 
         | is the same as:                   [(1, 2); (3, 4)]
         | 
         | That's just hard to read. I don't mind `;` being a separator,
         | but tuples without parentheses is just annoying to look at in
         | 9/10 places.
        
           | Quekid5 wrote:
           | There was a Revised Syntax (not sure if it's still a thing)
           | which smooths out some of the most egregious warts. It
           | requires preprocessing, but it was part of the standard
           | distribution last I looked.
           | 
           | The most egregious for me was actually ;; being so close to ;
           | to type and you'd be staring at weird type errors for ages
           | before realizing what had gone wrong. I realize that this may
           | be hard to convey to people who haven't used OCaml, but: The
           | ;; terminates a top-level definition -- which was usually
           | type-inferred when I was using OCaml... so it would lead to
           | all sorts of "weird" type errors, when all that was missing
           | was a simple ;
           | 
           | EDIT: Just for context, last looked (seriously) at OCaml ~15
           | years ago, last wrote it ~20+ years ago. It's cool, but it
           | ended up just being my gateway drug to Haskell... for which I
           | thank it :)
        
           | yodsanklai wrote:
           | I agree the second form is preferable to the first one. But I
           | think, most people will use the second form anyway. In my
           | projects, ocamlformat chooses the second option.
           | 
           | In the case of OCaml, we can certainly find a few oddities,
           | but really, I never found the OCaml syntax to be such an
           | issue or to make me unproductive in any way. I'm much more
           | prone to syntax errors in Haskell actually.
           | 
           | I suspect people who complain are mostly used to C-like
           | syntax and aren't familiar with any language of the ML
           | tradition. I agree that the barrier to entry would be lower
           | if the syntax was more "mainstream", but I don't find there's
           | really anything wrong with OCaml syntax, except that it's
           | "different".
        
             | 0x457 wrote:
             | Oh, I don't think Ocaml syntax is an issue at all, I like
             | most of it. I'm saying that, syntax isn't the least
             | important part of a language - look at how many languages
             | compile to JavaScript without bringing anything new ("new"
             | being something like types in TypeScript).
             | 
             | > I suspect people who complain are mostly used to C-like
             | syntax and aren't familiar with any language of the ML
             | tradition
             | 
             | Yes, that's probably it. Can't really blame them - C, C++,
             | Java, C#, PHP been very popular for long time. When I first
             | saw Erlang, I thought it's a language for aliens.
        
         | kevinmgranger wrote:
         | I can't say I'm very familiar with OCaml, but I'm excited to
         | see where multicore takes it regarding your second point.
        
         | goto11 wrote:
         | > I'm surprised people care about the syntax... that's pretty
         | much the least important part of the language.
         | 
         | The syntax is the user interface of a language. It matters.
        
         | dmitriid wrote:
         | > I'm surprised people care about the syntax... that's pretty
         | much the least important part of the language.
         | 
         | Until the syntax starts impeding with your understanding of the
         | code, or is impossible to look up in documentation/google.
         | 
         | OCaml IMO is a bit over the line with the number of ascii art
         | used.
         | 
         | I definitely agree with your other points. Though I only
         | touched OCaml very briefly.
        
       | lou1306 wrote:
       | I feel like F# addresses quite a few items on the "dislike" list:
       | 
       | * It has // for single-line comments
       | 
       | * You can use newlines as a list separator, as in:
       | let some_list = [           1           2           3         ]
       | 
       | * Similarly, multiple let-bindings can be separated by newlines
       | and the "in" is optional in most cases
       | 
       | This comes from some drawbacks: for starters, when I mention
       | "newlines", it's actually significant whitespace, so you may or
       | may not like it (as a heavy Python user, I just don't care).
        
         | devmunchies wrote:
         | Yes, and if you use a code formatter, like Fantomas, it can
         | automatically modify code to be in the more legible format
         | (like Prettier.js), so you don't confuse tuples with list
         | elements.
         | 
         | I've been using f# for a couple years, and after the honeymoon
         | phase is over, I've started to really value the benefit of
         | native interop with dotnet libraries.
         | 
         | Most enterprise SDKs/libraries (e.g. AWS S3, Stripe, Twilio,
         | Rollbar, etc) have a dotnet SDK, and it just drops into an F#
         | codebase as if it were a 1st party lib (you reference them
         | using object-oriented dot notation instead of functional style,
         | but still it just works).
         | 
         | Even when Microsoft puts work into, for example, cryptography
         | security updates or JSON parsing performance, F# benefits from
         | that.
        
       | yallop wrote:
       | > Things I Disliked        > [...]        > * using ; heavily as
       | element separator (e.g. in lists and records):        >         >
       | let some_list = [1; 2; 3; 4; 5]        >         > You get used
       | to this, but it's a pretty big departure from the norm to use
       | commas. I wonder what's the reasoning behind this.
       | 
       | It appears to be a result of the limitations of early parser
       | technology, as Dave MacQueen explains:                   "One of
       | the kind of interesting things is that the parser was written
       | based on Vaughan Pratt's precedence parser [...] and it had the
       | peculiar property that it was hard to reuse symbols for multiple
       | syntactic purposes, and hence you get things like comma used for
       | pairing that means you have to use semicolon for list separator,
       | that means you have to use semicolon-semicolon for statement
       | separator, so there's some peculiarities based on the fact that
       | we didn't really know how to parse and we accepted this quick
       | hack from Vaughan Pratt"
       | (https://www.youtube.com/watch?v=ua3EYopCURo&t=179s)
        
         | acjohnson55 wrote:
         | My biggest frustration with OCaml is having to deal with all of
         | that cruft. I've learned many languages over the years, and I
         | think I've just reached the point where I've lost patience with
         | having to deal with what I would consider substandard syntactic
         | elegance.
        
           | cardanome wrote:
           | I don't mind the cruft. I think a bit of harmless quirks can
           | give a language character.
           | 
           | It actually makes the learning easier. Now that I know the
           | story why, I have memorized how elements are seperated in
           | OCaml for probably the rest of my life. I just need to
           | remember the story.
           | 
           | Plus not reusing symbols for multiple syntactic purposes
           | actually fits nicely into the general Ocaml philosophy. Plus
           | is makes my complexity-hating, minimalist heart happy.
           | 
           | Though I am at that point in my life where I don't really
           | care about syntax that much to begin with. Yes syntactic
           | complexity matters. How fast it can be parsed, how easy
           | macros are implemented, these things can matter but the
           | actual syntax: boring. White-space sensitive or not, curly
           | braces or begin/end and all that stuff is so dull. I am happy
           | with whatever.
        
           | p4bl0 wrote:
           | If using semicolons instead of commas is enough of a
           | showstopper for you it's probably that you just don't have a
           | need for the language :).
        
           | WastingMyTime89 wrote:
           | Yes but OCaml syntax is Pascal inspired. It's always going to
           | be a lot more elegant that anything inspired by the horror
           | that is the B syntax. It's just less familiar to people who
           | grew up using C, Java or JavaScript.
        
           | tialaramex wrote:
           | This sort of thing is why Rust's Editions are great and why
           | Vittorio Romeo's Epochs (P1881) for C++ would have been the
           | right choice.
           | 
           | I like Editions because of the cultural consequences, Rust's
           | community assumes they _can_ fix things and so they set out
           | with that goal, even in cases where Editions won 't quite do
           | it - while the C++ community tends to accept the state of the
           | language as a static fact and just "take it". But this sort
           | of thing isn't about the cultural effects, it's a direct
           | technical achievement.
           | 
           | If OCaml had Editions, it could say OK, that syntax was a bit
           | rubbish, here's 2023 syntax which fixes two things everybody
           | hated, get back to us over the next few years and we'll
           | decide if there are further changes needed. _Without_ losing
           | all existing OCaml software or demanding expensive rewrites.
           | 
           | Even better, changes of the sort in Editions are mechanical.
           | It can take a bit of creative work to do it _nicely_ but the
           | transformations can be automated, so people who have  "old
           | OCaml" and wish they had "new OCaml" can push a button and
           | get on with their day. Having both this and the feature which
           | keeps old code working unchanged, add up to an experience
           | where the community can move forward, on syntax at least, and
           | not be trapped with yesterday's mistakes.
        
           | zumu wrote:
           | The syntax is a little unorthodox, but just having a literal
           | syntax _at all_ for things like lists/arrays beats having to
           | call `new` on some random class you have to import and then
           | doing a bunch of in place updates to add all the data.
        
             | dmitriid wrote:
             | In this respect C# has knocked it out of the park with
             | shorthand initialisation syntax for arrays and objects. But
             | it's newer and could look at what other languages are
             | doing/not doing in that regard.
        
           | toolslive wrote:
           | what's your stance on the curly braces (which is also a
           | consequence of early parser technology) ?
        
             | galangalalgol wrote:
             | What are some good alternatives? I don't find begin and end
             | as easy to spot at a glance if the indentation is off. I'm
             | not sure why I don't like indentation based, but I don't in
             | practice. A good IDE helps me care less, and I don't think
             | I could write python well without a good IDE anyway.
        
             | acjohnson55 wrote:
             | I think they're often helpful for reading, but I admire
             | what Scala did in Scala 3 to eliminate their necessity.
        
               | yawaramin wrote:
               | Scala 3 actually doesn't really eliminate braces in any
               | meaningful way. Sure, they're optional for delimiting
               | traits, classes, and objects. But braces are heavily used
               | for block scoping in Scala too. E.g. a very common
               | pattern:                   retry(Seq(1.second, 2.second,
               | 3.second)) {           // some action that can fail
               | }
               | 
               | This still requires the braces as of right now. I think
               | the syntax changes will just confuse more people than it
               | helps, at least for the time being.
        
               | AzzieElbab wrote:
               | That is a curried parameter in {}. Those braces are not
               | for scoping. They basically define a lambda. You can
               | probably use () instead
               | 
               | you can also use import language.experimental.fewerBraces
               | with nightly builds to write code like this
               | 
               | List(1,2,3).map: c => ...
        
         | tomp wrote:
         | No, it's actually because , (comma) denotes a tuple.
         | [1, 2; 3, 4]
         | 
         | is a list of tuples, of type (int * int) list, equivalent to
         | [(1, 2); (3, 4)]
        
           | cwzwarich wrote:
           | This phenomenon is actually another example of the phenomenon
           | he mentions. In strict precedence parsing, operators are
           | assigned meaning rather than productions of a grammar (which
           | would could those operators in distinct contexts), so once
           | you've decided a comma indicates a tuple, it's easier to just
           | allow this syntax.
        
           | Athas wrote:
           | I never understood the motivation for allowing tuples without
           | surrounding parens. There are a few very simple functions
           | that look cuter this way, but it constantly trips me up in
           | more complex situations.
        
             | a-nikolaev wrote:
             | No parentheses can be nice for cleaner pattern matching,
             | e.g. something like this:                 match a, b with
             | | 1, 2 -> x       | _ -> y
        
           | goodoldneon wrote:
           | The "comma makes a tuple" behavior is a big gotcha I've
           | experienced in Python. I wish that behavior didn't exist
        
             | LynxInLA wrote:
             | Which version of that are you talking about in Python? The
             | biggest related gotcha I've seen in Python is when you have
             | a trailing comma `x = 1,` and accidentally create a tuple.
        
               | goodoldneon wrote:
               | Yea that's the most common gotcha
        
         | tshaddox wrote:
         | The article briefly mentions ReasonML, which offers a different
         | syntax which aims to be more familiar to JavaScript programmers
         | but is also likely to be more familiar to most programmers of
         | C-family languages.
         | 
         | There's also ReScript, which is a very similar alternate syntax
         | which sort of split off from the ReasonML community in a
         | confusing and complicated sequence of events which is
         | frustrating to try to follow for someone who was just
         | interested in the programming language and tooling:
         | https://rescript-lang.org/blog/bucklescript-is-rebranding
        
           | dmitriid wrote:
           | That split was really bad. At the height if its popularity
           | (yes, there was a brief moment in the sun) it was also
           | influencing the OCaml community IIRC, bringing improvements
           | like friendly error messages and syntax improvements.
           | 
           | Now though... Who cares about either of the Re* languages?
        
             | sairion wrote:
             | I think ReScript community is pretty active right now, I
             | have big expectations about future 10.x releases (I'm
             | working for a company uses ReScript as a main programming
             | language) there are less buzz recently though.
        
             | kn8 wrote:
             | ReScript community is well and alive and is actively
             | working on improving the ReScript compiler and tooling. V10
             | just came out with records with optional fields -
             | https://forum.rescript-lang.org/t/ann-
             | rescript-v10-released/.... Async/await is in the works. The
             | language is really really good (especially say comparing to
             | TypeScript). Make sure to check it out.
        
             | splintercell wrote:
             | ReScript is amazing. I really don't know much about the
             | split (it's not like I didn't try to understand it, I just
             | can't understand the anger of non-Ocaml developers at the
             | split).
             | 
             | Rescript allows me to write Javascript in a sound type
             | system, while remaining very close to how you would write
             | code in Javascript.
             | 
             | Rescript to me feels like Typescript + a very prescriptive
             | linting system which prevents a lot of problems, and since
             | the linting system wouldn't let you do certain things,
             | might as well get rid of them from the Type checker, this
             | results in a much faster compiler.
        
               | sairion wrote:
               | I have been using ReScript for (almost) a year as a
               | production programming language. There were a few
               | limitations and confusions at first, (and I don't think
               | it will be replacing TypeScript in any near future) but I
               | can't even think about going back to a work environment
               | uses TypeScript, the dev experience is so good :)
        
           | rtlfe wrote:
           | > The article briefly mentions ReasonML, which offers a
           | different syntax which aims to be more familiar to JavaScript
           | programmers but is also likely to be more familiar to most
           | programmers of C-family languages.
           | 
           | One thing I don't like about this is that they've replaced:
           | 
           | > let x = 1 in
           | 
           | with
           | 
           | > let x = 1;
           | 
           | In plain OCaml you only use semicolons on lines that evaluate
           | to unit, so they're a clear indicator that you've done
           | something with side effects. ReasonML loses this useful
           | visual distinction in order to look more like JavaScript.
        
             | cheriot wrote:
             | Agree. ReasonML threw the baby out with the bathwater. If
             | ever there's a language to not immatate it's Javascript.
             | 
             | Would be interesting to see a something that updated some
             | ocaml quirks, but stayed true to the spirit of the syntax.
             | Ie comments and multiply but not ;
        
       | dustingetz wrote:
       | How is macros or metaprogramming or anything that fills a similar
       | role?
        
         | toolslive wrote:
         | there's BER MetaOCaml
         | 
         | https://okmij.org/ftp/ML/MetaOCaml.html
        
         | sleepydog wrote:
         | Not great, not terrible; the language supports annotations
         | which mean nothing to the compiler but which pre-processors can
         | take advantage of, and there is a framework called ppx which
         | you can use to write your own preprocessor. There exist many
         | pre-processors to do things like add inline tests, generate
         | getter/setter/pretty-printing functions, and so on. Here is an
         | example:
         | 
         | https://github.com/ocaml-ppx/ppx_deriving
        
       ___________________________________________________________________
       (page generated 2022-08-29 23:00 UTC)