Python to OCaml: Retrospective
roscidus.com
roscidus.com
[1] http://roscidus.com/blog/blog/2014/02/13/ocaml-what-you-gain...
I'd like to know more about that. Have I missed something?
Regardless, excellent write-up. Thank you.
Instead, the OCaml created a pair of pipes and spawned a Python subprocess (you need to use two pipes, not a single socket, because Windows doesn't support Unix sockets).
The protocol was asynchronous (replies can arrive out of order). Although the original JSON bridge is now gone, the new "0install slave" command (which allows other programs to control a 0install subprocess) uses a very similar system. It's documented here:
The summary:
----
"OCaml’s main strengths are correctness and speed. Its type checking is very good at catching errors, and its “polymorphic variants” are a particularly useful feature, which I haven’t seen in other languages. Separate module interface files, abstract types, cycle-free dependencies, and data structures that are immutable by default help to make clean APIs.
Surprisingly, writing GTK GUI code in OCaml was easier than in Python. The resulting code was significantly shorter and, I suspect, will prove far more reliable. OCaml’s type checking is particularly welcome here, as GUI code is often difficult to unit-test.
The OCaml community is very good at maintaining API stability, allowing the same code to compile on old and new systems and (hopefully) minimising time spent updating it later."
----
This gives me the impression that OCaml is also a joy to program with, and additionally is more reliable and better at catching errors earlier than Python.
One thing I don't think the tutorial mentions, but which helps a lot, is turning on all warnings ("-w A"). The tutorial also fails to mention ocamlbuild, so you start by compiling things manually, which makes everything harder than it should be.
This makes a good case for prototyping in Python and only moving to something else when performance becomes an issue.
I mentioned UNIX, because on Windows my to go language for private scripts is F#.
F# interactive is what powershell/ISE wants to be, when it grows up and drinks the magic potion of awesomeness.
F# scripts for my own stuff, Powershell when those scripts need to be shared across the team or I need to interoperate with third party cmdlets.
It is quite terse, specially because Powershell has a bit of VB flavour to its syntax, mixed with attributes everywhere.
I rather use the cleanliness of the ML syntax, if possible.
I guess it's not that bad after looking at this for example:
https://github.com/0install/0install/blob/master/ocaml/zeroi...
------
A couple of people have asked why you might choose OCaml over other languages. I've not done as much OCaml work as others on this thread (I work primarily on ReactJS (Facebook/Instagram's) functional UI framework), but I can offer a different perspective as someone who is outside of the OCaml community, but asking the same questions. Here are some of my personal findings. I'll narrow any comparison down to the ML family of languages. Java/C++/ and many other languages are just now beginning their slow, but inevitable evolution into becoming a dialect of ML (which IMHO is a sort of admission of the ML/functional family superiority). Once you embrace the power of pattern matching, it's hard to use anything but an ML family language (StandardML/Haskell/F#/OCaml). I would program in any one of those languages over Java/C++/Objective-C/JS. Practical reasons why you might choose OCaml:
- OCaml's records aren't as elegant as SML's but OCaml has labeled arguments with optional default values which can satisfy many of the reasons why you'd use records as arguments in the first place (and may be even more powerful in some cases).
- Two modes of compilation (fast native executable XOR fast compilation). Who doesn't like options.
- All the benchmarks I can find show that OCaml is very fast (around as fast as C++).
- Excellent JS target and and apparent commitment to maintaining it (as someone building a JS library, this is very important to me) (and as someone who wants to build apps and be able to instantly share them with everyone in the world.)
- Someone has built an autocomplete plugin for Vim/Emacs (merlin). ("VimBox" (https://github.com/jordwalke/VimBox/) has configured it to complete as you type - like in Visual Studio etc.)
- On very rare occasion, you'll run into a problem that is inherently better suited to OO (dynamic dispatch). I can usually find a way to solve it with functors/modules, but it's nice to know that you have OO in your back pocket in case you ever need it. It's also nice to know you probably won't have to.
- Finally, a common package manager (OPAM) is becoming standard. I look forward to seeing how OPAM helps make the new dev experience and the code-sharing/development experience seamless.
- The module system is very powerful (SML's). Haskell does not have this, and strangely F# dropped it. (I hear, Haskell's type classes fulfill similar roles (but with more sugar)).
- There's usually ocamlyacc grammars for most languages. Most examples of languages, type systems, parsers are already in OCaml (or ML). It's a nice (but small) perk.
- Predictability. OCaml is not lazy by default. Lazy computations could become problematic for low-latency applications (such as UIs) if a lot of computation becomes is deferred until the moment a final dependency has been satisfied, but by that time you may be close to your screen refresh deadline and it may lead to a dropped frame. It would have been better to have been computing while waiting for a final dependency. I'm not sure if Haskell (a lazy language) has had this problem. You can opt into laziness in OCaml if you would like to.
- Mutability. I feel strange saying this, as such a huge proponent of immutability, but sometimes you just need to hack something in place, mutate some state and come back to clean it up later. (You can still use monads in OCaml).
- Tagged Variants (no need to predeclare variants, just pattern match on them and OCaml ensures that only properly matched values ever make their way into that expression).
- Industry use is growing. OCaml is used here at Facebook and many other places as mentioned.
- There are many abstractions to choose from (Records, Objects, Modules, Functors, First Class Modules, GADTs, ...).
OCaml Cons: - There are many abstractions to choose from (Records, Objects, Modules, Functors, First Class Modules, GADTs, ...). (Edited for formatting)
It would be interesting to get your take on the toolstack we're building using OCaml - http://nymote.org (I'm aware the copy on the site needs works but it's the tools I'm referring to).
F# runs on the standard .net type system which is not able to do type classes, modules or higher kinded generics. On the other hand you have compatibility to all .net libraries which is a huge plus.
25.52% camlp4 ocamlrun [.] caml_interprete
14.60% ocamlopt.opt ocamlopt.opt [.] 0x000000000016ec61
10.51% ocamlfind ocamlfind [.] caml_interprete
Looks like ocamlfind is the bytecode version too ... I opened a bug.Take for instance compiler development: half a decade ago, updates were rare and marginal. Nowadays you can expect a new compiler version every single year with lots of exciting features.
[1] https://sympa.inria.fr/sympa/arc/caml-list/2014-05/msg00146....
Epilogue
Mirage unikernel - an operating system written in OCaml
(the Mirage web-site is all implemented in OCaml, down to
and including the TCP/IP stack!). That will have to be
the subject for another blog post though...
I am looking forward to such posts. Keep up your good work!I don't think language age has any bearing on quality or usefulness.
Yeah, and fanbois gonna fanboi. He found something that works better for his use case. Sure, Python has has more programmers available, but that's because it's the flavor of the week (thanks to Google, let's be honest). In 3 years it may be the language time forgot. It makes a lot more sense to pick something you enjoy programming in and makes your life easier than something that everyone else thinks is the shit. Python has its place, and that place is not everywhere.
With lisp, I edit, eval (simple command in my editor), see result. If I'm building a game or a long-running app, I can redefine functions while it's running without doing a full recompile and having to try and get back to the state the app was in when I wanted to test my change.
So you get the ability to live-code while the app is running. Once you get used to being able to do this, leaving your editor and opening to shell to test your app seems like a barbaric exercise.
So a good REPL (lisp or not, doesn't matter) can make the experience a lot more interactive and experimental that your average write -> save -> compile -> run cycle.
It remains an extremely useful tool though.
With modern type systems employing structural subtyping, row polymorphism, proper variance and covariance handling and other advanced techniques static typing becomes a very powerful tool.
On the other hand, there are correct programs which we still don't know how to type. This means that there are programs we just can't write in statically typed languages, at least not yet.
Anyway, I'm not arguing against or in favour of static or dynamic typing. I'm simply stating the fact that choosing one over the other is still just a matter of preference and personal decision about which set of tradeoffs you like better.
It's exactly the same as with Vim vs. Emacs debate. I can't believe I got downvoted because of pointing this out. I believe that there is a place and a good way of discussing relative merits of static and dynamic type systems, but simply stating your preference in a thread about something unrelated is most definitely not a good way.
I know this is true, but is it common? What would be a realistic case for this? Realistic as in, "code most people who are fans of dynamic typing find themselves writing". Contrived examples can always be found, but if someone told me they don't use static typing because there are programs that cannot be typed, I'd ask them "how often do you write that kind of programs?".
I don't think that's right. If something can't be type-checked then you just add an "assert" and do the check dynamically.
For example, in 0install I need to ask the SAT solver which version of a program I should use. I pass it a load of SAT variables, each containing a user data field with the attached program details, run the solver, and get back the selected variable. The SAT problem also contains other variables, with other kinds of data.
I know the user data field for the selected result will be of type program details, but I couldn't figure out how to let the compiler check this statically. It's not a problem; I just check the type and "assert false" if it's wrong. I still get the benefit of static checking almost everywhere else in the code.