I took this course ten years ago with Didier Remy, I was very disappointed.
First of, the course was called "Operating Systems", and I was expecting subsetting like the Tannenbaum, explaining the theory and practice behind kernels. The course actually was about Unix system programming, and solely about that. At least the page is properly named.
Second, I think OCaml is an amazing language, but frankly it's a terrible choice for this course. One needs the right tool for the right job. No particular " insight " is gained as the page alleges, beyond the insight that, gee, C would probably be a better lanhuage to interface with the system it was designed for!
Our project consisted in implementing the "ls" command in OCaml, which meant mostly covering all the corner cases brought by different flags. It wasn't interesting, it didn't teach valuable skills.
Functional programming languages shine when they deal with complex, recursive data structures, not for simple tasks which are primarily IO and need to handle many cases.
> Functional programming languages shine when they deal with complex, recursive data structures
While I obviously can't comment on the details of the course you took a decade ago, I do have to disagree vehemently with this. OCaml is close to as ideal a systems programming language as I've ever used since:
- it has a simple, stable and predictable runtime with strict evaluation semantics, so you can identify what statements allocate memory by inspecting code.
- the compilation to native code is fast and Unix-like, with standard object files generated that can be linked to and from C programs easily.
- the memory representation of values is uniform and native code debugging with gdb/lldb works great, thanks to the DWARF symbols emitted.
- OCaml's basic language features such as algebraic data types and exhaustive pattern matching are fantastic for both building low-level programs, and refactoring them in the future as they inevitably get more complex.
> not for simple tasks which are primarily IO and need to handle many cases.
And this is exactly where libraries like Async or Lwt are so useful, since you can juggle millions of concurrent threads and still do high-level programming without getting lost in the noise. Error monads, failure monitors, function wrappers to ensure resources get freed, can all be built directly within the language itself using the usual ML abstractions, and the compiled code is still lightweight and natively compiled.
For those interested in reading more about the runtime system in OCaml, the entire third part of Real World OCaml is dedicated to this topic: https://realworldocaml.org/v1/en/html/pt03.html
What's the current state of parallel execution with OCaml? Historically, I've been attracted to the type system and I think it's generally one of the most beautiful languages out there, but I build things that need to take advantage of many cores at once. Are there now at least nice wrappers around going multi-process like python's multiprocessing library?
> - the memory representation of values is uniform and native code debugging with gdb/lldb works great, thanks to the DWARF symbols emitted.
Besides being able to get a simple backtrace, I've always had nothing but headaches trying to print out variables. It's not tightly integrated with gdb, so the default "p my_ocaml_var" of course doesn't work and info locals rarely if ever works. Only time the debugging is good is when you get to the C code underlying the system calls.
I would love for this not to be the case, but I'm not sure if anyone is working on making OCaml better to debug in gdb.
> I'm not sure if anyone is working on making OCaml better to debug in gdb
Mark Shinwell is working on just this; he has a very impressive branch of OCaml which can do OCaml-level source backtraces in gdb; WIP tree is here for anyone who wants to glance at the patches: https://github.com/mshinwell/ocaml/compare/ocaml:4.02...4.02...
Thanks for the links, I'll have to take a look at that gdb/OCaml debugging video. Might as well dive into the OCaml internals a bit too. I just really wish OCaml would move to a fully threaded execution model instead of forcing evented systems on everyone.
I can't really usefully answer that question without knowing more about what your purpose is.
If your purpose is to learn how to program in a functional style, then either language is fine. Other than that, the main difference between the two is purity/effects, lazy/strict, and type-classes/modules in Haskell and OCaml. That all changes the specifics of the code being written quite dramatically.
I was asking about the exact uses murbard2 detailed, for which murbard2 thought OCaml was not ideal... not asking which language I should learn to understand functional programming
Anyway, I'm not sure what murbard2 is objecting to. The only thing I got is "Functional programming languages shine when they deal with complex, recursive data structures, not for simple tasks which are primarily IO and need to handle many cases."
Well, OCaml-the-language does IO perfectly fine (even if you want to augment/replace the standard library, which admittedly does few things "perfectly fine"), and languages with algebraic datatypes are very good at handling "many cases" in a typesafe way.
C is not a great language for the sort of stuff in this course. Apart from good documentation. Mostly it is not performance critical, and often deals with strings. The C interfaces are very verbose and easy to make mistakes in. Hence the popularity of Go etc. IPC,sockets and so on is a core framework of programming so wide language support is good.
> A rich history of segfaults and security issues is not proof enough?
The most popular language in the world -- the language that's being used to write the largest, most complex software -- will surely have a rich history of bugs and security holes. That will be the case whether or not said language is C.
> C got its place in the IT world thanks to UNIX's adoption.
I disagree with your implicit claim that C's position as the most popular systems programming language is not due the language's intrinsic qualities. Luck was a factor but not the only one. It cannot be the only one. The language is just good -- or at least good enough.
> It is nothing more than a portable macro assembler with all advantages and more importantly the disadvantages that it entails.
Stop the hyperbole. The language is quite a bit more than that. For one, it's structured.
> I disagree with your implicit claim that C's position as the most popular systems programming language is not due the language's intrinsic qualities.
I am old enough to remember when knowing C was only required for anyone lucky enough to work in one of those shiny UNIX workstations. The language had barely any use outside of the UNIX workstation world and those compilers supported mostly dialects, not the full language.
Only after business started to get UNIX deployed in bigger scale, C knowledge started to matter on the CV.
> Stop the hyperbole.
It is not an hyperbole. Mesa, Cedar, Algol variants, Pascal variants and Modula-2 offered much higher features while allowing for systems programming.
> The language is quite a bit more than that. For one, it's structured.
So what that C is structured. Any PC and Amiga macro assembler had powerful macro languages that allow to write structured assembly code.
The end result is barely any different than using K&R C or C89, except that C wins on the portability side.
> Functional programming languages shine when they deal with complex, recursive data structures, not for simple tasks which are primarily IO and need to handle many cases.
I think most of the advantages of FP languages (as they exist today) become disadvantages as your data structures get more and more complex. Efficient mutability becomes necessary. Pattern matching breaks down as (G)ADTs can no longer encode useful invariants. Referential transparency becomes useless once you realize you want explicit sharing. Laziness and space leaks become a huge PITA. The RTS and the mandatory GC start getting in your way as it gets harder and harder to eek out performance from your code. etc etc..
> I think most of the advantages of FP languages (as they exist today)
You seem to be describing Haskell with that rather overgeneral (and incorrect) statement above. OCaml supports mutation and explicit sharing just fine, and is strict by default. As for the rest, as you get closer to needing manual resource control, it just gracefully devolves.
I seem to be describing Haskell because Haskell is the epitome of an FP language. If FP is truly a self-contained practical, versatile paradigm by itself, then Haskell would exemplify this.
There is no "true" definition of functional programming. You can, of course, make the argument that Haskell is the one true functional language, but this is not what is generally accepted (eg, OCaml or Erlang are usually considered functional languages - and most of these languages have strict semantics).
All I'm saying is that if we plot languages on a spectrum, where one end corresponds to functional programming and the other to, say, imperative programming, then Haskell will be most closely to the FP end than any other practical language. Haskell embodies the most of the tenets of FP.
This is primarily what I use functional languages for so far, so naturally I disagree. As long as their aren't stringent performance requirements (though functional languages like Ocaml and Haskell are pretty fast) I find functional languages to be a generally better fit.
Also parsing and string handling in C is worlds more difficult than something like Parsec using parser combinators.
This sounds really cool. I currently TA a CS course that deals primarily with OCaml so it is great to have real world applications/uses I can show to students in the class.
31 comments
[ 3.3 ms ] story [ 83.6 ms ] threadFirst of, the course was called "Operating Systems", and I was expecting subsetting like the Tannenbaum, explaining the theory and practice behind kernels. The course actually was about Unix system programming, and solely about that. At least the page is properly named.
Second, I think OCaml is an amazing language, but frankly it's a terrible choice for this course. One needs the right tool for the right job. No particular " insight " is gained as the page alleges, beyond the insight that, gee, C would probably be a better lanhuage to interface with the system it was designed for!
Our project consisted in implementing the "ls" command in OCaml, which meant mostly covering all the corner cases brought by different flags. It wasn't interesting, it didn't teach valuable skills.
Functional programming languages shine when they deal with complex, recursive data structures, not for simple tasks which are primarily IO and need to handle many cases.
While I obviously can't comment on the details of the course you took a decade ago, I do have to disagree vehemently with this. OCaml is close to as ideal a systems programming language as I've ever used since:
- it has a simple, stable and predictable runtime with strict evaluation semantics, so you can identify what statements allocate memory by inspecting code.
- the compilation to native code is fast and Unix-like, with standard object files generated that can be linked to and from C programs easily.
- the memory representation of values is uniform and native code debugging with gdb/lldb works great, thanks to the DWARF symbols emitted.
- OCaml's basic language features such as algebraic data types and exhaustive pattern matching are fantastic for both building low-level programs, and refactoring them in the future as they inevitably get more complex.
> not for simple tasks which are primarily IO and need to handle many cases.
And this is exactly where libraries like Async or Lwt are so useful, since you can juggle millions of concurrent threads and still do high-level programming without getting lost in the noise. Error monads, failure monitors, function wrappers to ensure resources get freed, can all be built directly within the language itself using the usual ML abstractions, and the compiled code is still lightweight and natively compiled.
For those interested in reading more about the runtime system in OCaml, the entire third part of Real World OCaml is dedicated to this topic: https://realworldocaml.org/v1/en/html/pt03.html
Lwt also has the Release framework which does multiprocess: https://github.com/andrenth/release
and more if you search through OPAM.
Besides being able to get a simple backtrace, I've always had nothing but headaches trying to print out variables. It's not tightly integrated with gdb, so the default "p my_ocaml_var" of course doesn't work and info locals rarely if ever works. Only time the debugging is good is when you get to the C code underlying the system calls.
I would love for this not to be the case, but I'm not sure if anyone is working on making OCaml better to debug in gdb.
Mark Shinwell is working on just this; he has a very impressive branch of OCaml which can do OCaml-level source backtraces in gdb; WIP tree is here for anyone who wants to glance at the patches: https://github.com/mshinwell/ocaml/compare/ocaml:4.02...4.02...
Also a nice talk from a couple of years ago by him on some tips and tricks for using gdb/OCaml: https://www.youtube.com/watch?v=NF2WpWnB-nk
If your purpose is to learn how to program in a functional style, then either language is fine. Other than that, the main difference between the two is purity/effects, lazy/strict, and type-classes/modules in Haskell and OCaml. That all changes the specifics of the code being written quite dramatically.
Anyway, I'm not sure what murbard2 is objecting to. The only thing I got is "Functional programming languages shine when they deal with complex, recursive data structures, not for simple tasks which are primarily IO and need to handle many cases."
Well, OCaml-the-language does IO perfectly fine (even if you want to augment/replace the standard library, which admittedly does few things "perfectly fine"), and languages with algebraic datatypes are very good at handling "many cases" in a typesafe way.
Not to mention string handling in C is just awful.
The most popular language in the world -- the language that's being used to write the largest, most complex software -- will surely have a rich history of bugs and security holes. That will be the case whether or not said language is C.
It is nothing more than a portable macro assembler with all advantages and more importantly the disadvantages that it entails.
I disagree with your implicit claim that C's position as the most popular systems programming language is not due the language's intrinsic qualities. Luck was a factor but not the only one. It cannot be the only one. The language is just good -- or at least good enough.
> It is nothing more than a portable macro assembler with all advantages and more importantly the disadvantages that it entails.
Stop the hyperbole. The language is quite a bit more than that. For one, it's structured.
I am old enough to remember when knowing C was only required for anyone lucky enough to work in one of those shiny UNIX workstations. The language had barely any use outside of the UNIX workstation world and those compilers supported mostly dialects, not the full language.
Only after business started to get UNIX deployed in bigger scale, C knowledge started to matter on the CV.
> Stop the hyperbole.
It is not an hyperbole. Mesa, Cedar, Algol variants, Pascal variants and Modula-2 offered much higher features while allowing for systems programming.
> The language is quite a bit more than that. For one, it's structured.
So what that C is structured. Any PC and Amiga macro assembler had powerful macro languages that allow to write structured assembly code.
The end result is barely any different than using K&R C or C89, except that C wins on the portability side.
EDIT: some extra clarification and formatting
I think most of the advantages of FP languages (as they exist today) become disadvantages as your data structures get more and more complex. Efficient mutability becomes necessary. Pattern matching breaks down as (G)ADTs can no longer encode useful invariants. Referential transparency becomes useless once you realize you want explicit sharing. Laziness and space leaks become a huge PITA. The RTS and the mandatory GC start getting in your way as it gets harder and harder to eek out performance from your code. etc etc..
You seem to be describing Haskell with that rather overgeneral (and incorrect) statement above. OCaml supports mutation and explicit sharing just fine, and is strict by default. As for the rest, as you get closer to needing manual resource control, it just gracefully devolves.
This is primarily what I use functional languages for so far, so naturally I disagree. As long as their aren't stringent performance requirements (though functional languages like Ocaml and Haskell are pretty fast) I find functional languages to be a generally better fit.
Also parsing and string handling in C is worlds more difficult than something like Parsec using parser combinators.