This is the home page for the Ocaml (Objective CAML) track of CS 11. This information is for the Spring 2015 term.
This track has been created in response to a growing demand from students for a track which teaches the Objective CAML (Ocaml) programming language, and also teaches functional programming, which is one of the programming paradigms that is supported directly by the Ocaml language.
All the administrative information for this track is on this page.
The full name for Ocaml is Objective CAML. The "objective" part means that it's an object-oriented extension to the CAML language. "CAML" is short for "Categorial Abstract Machine Language", and we won't discuss what that means here ;-) Ocaml is a computer language in the ML family (another language in the same family is Standard ML). Some of the many features of Ocaml that make it different from other computer languages include:
It supports functional programming, which we discuss below. In short, functions are data and can be passed as arguments to other functions, created on-the-fly, and returned from functions.
It is a type-safe language, which means that all values have types and all types are checked at compile time. Type errors cannot occur at run time. If you've programmed in languages like C, C++, or Java, you're used to compile-time type checking, but Ocaml is *much* stricter than those languages. The type system is also much more powerful than in those other languages, so this strictness doesn't cause problems (at least not very often).
To minimize the need to declare types for all values, the language features type inference whereby the types of most values can be automatically derived by the compiler. This makes the code much less cluttered and more readable, almost like the code in a scripting language.
It is very easy to define new data types which are checked for correctness just like built-in data types are.
One class of types is called algebraic data types which are like the union types of C, except that they're type-safe. Once you've used algebraic data types, you'll wonder how you ever lived without them. In conjunction with this, Ocaml has powerful pattern-matching features which make it easy to use these types.
Ocaml features polymorphic types which are types which are parameterized over other types (e.g. list of "a", where "a" is an arbitrary type). This allows you to define functions that work the same way over a large number of types.
There is a powerful module system which allows the programmer to package up functions and types in very flexible ways. In addition, you can define functors, which are basically functions which create new modules from old ones. Functors are a bit like C++ templates, but they're much more powerful and general (and also type-safe). Unlike C++ templates, they aren't implemented by macro-expansion, so there is a performance penalty associated with using them, but it's not large.
There is a simple and effective exception handling system.
Unused memory is reclaimed by garbage collection. You never have to free memory explicitly.
Code can be run interactively, compiled to byte-code, or compiled all the way to machine code. Ocaml programs compiled to machine code are very competitive with C or C++ programs in terms of their execution speed. Typically, Ocaml will out-perform C++ but be somewhat slower than C, although the precise results vary wildly depending on the application and the programmer. What's more interesting is that Ocaml is much easier to write programs in than C or C++, so it's a great language for increasing your productivity. Also, the advantage of using Ocaml vs. C/C++ grows as the data structures get more complex.
Ocaml supports object-oriented programming (the "objective" in "objective CAML"). We won't be covering that in this track (although maybe one day there will be an advanced Ocaml track that will cover it). Most Ocaml programmers don't use the object-oriented features because there are easier ways to get things done.
There are also lots of other features that there isn't enough space to cover here (as well as new ones that are being developed).
Ocaml is not a perfect language; some of the syntax is pretty nasty and confusing, error messages can be somewhat uninformative at times, the learning curve is steep, and there are times when the type system is too rigid for some applications. Despite this, most experienced programmers really enjoy using Ocaml, and many of us (including me) consider it among our favorite languages. It is definitely a very rewarding language to learn and to use.
Functional programming is a paradigm of programming (i.e. a particular way of writing programs) which contrasts greatly with the more common imperative and object-oriented paradigms. Ocaml supports all three paradigms, but it's most often used as a functional programming language (or as a mostly-functional programming language), and that how we will use it for most of this track. But what exactly is functional programming?
First off, functional programming means that functions are data. This means that functions can be passed as arguments to other functions, they can be created on-the-fly, they can be returned from a function, and they can be stored into data structures. Most computer languages (e.g. C) will allow you to pass a function as an argument to another function (although Java doesn't even allow that) but won't allow you to create a function on the fly. In addition to this, functions can hold references to data objects that existed when they were created and use them when they're invoked (such functions are called "closures" and are really like lightweight objects).
Another key aspect of functional programming is that data should be persistent. Put differently, it means that you avoid using mutable data as much as possible. So re-assigning the values of variables is strongly discouraged in functional programming. Most programmers probably think that it's impossible to program without using mutable variables all over the place, but it is indeed possible; it just requires you to think differently. Instead of using variables, you use constants: values that are bound to an identifier which don't change after being assigned. This is more like the way we think in mathematics: when we say that "a = 5" we mean that "a" represents the number "5" from now on, not just until we change it to something else. In fact, one of the interesting aspects of functional programming is that it's much more amenable to mathematical verification of algorithms than imperative programming is.
One result of the requirement that data should be persistent is that assignment statements are rarely used in functional programming.
Another result of the requirement that data be persistent is that
looping statements of the kind seen in C, C++ and Java
(for
loops and while
loops) are rarely used;
instead, we use recursion to do computations that involve loops.
Yet another result of the requirement that data be persistent is that we almost never use arrays for storing aggregate data; instead we use singly-linked lists. That's because singly-linked lists are persistent: you can add an element to the front of a list, and a variable which referred to the original list will still refer to the same data. Functional programmers tend to use lists a lot, and tend to use different data structures than imperative programmers.
Having said all that, sometimes imperative programming (with mutable data structures, assignments, arrays, etc.) is just the most efficient way to get a job done, so Ocaml also fully supports imperative programming. In general, though, you should strive to write your Ocaml programs in a functional way if possible, and only use the imperative features if you really need to (e.g. for a major boost in efficiency). Functional programs are much better-behaved than imperative ones, and they are usually much easier to debug.
Lecture 1
Lecture 2
Lecture 3
Lecture 4
Lecture 5
Lecture 6
Lecture 7
Current grades for all students are located on this page.
The Ocaml home page is at www.ocaml.org. There is a lot of tutorial material there. In particular, check out the Ocaml manual which is quite terse, but useful.
The textbook we'll be using for the track is Introduction to Objective Caml by Caltech's very own Jason Hickey. The entire book can be downloaded and printed or viewed at your convenience. I will be assigning readings from the text.
I really like the Tuareg Ocaml emacs mode. Don't write Ocaml code without it! (Unless you use vim, which also has an Ocaml mode.)
A useful tool for the interactive use of Ocaml is the rlwrap
program. You should download it and compile it yourself. It gives a
readline-like capability to Ocaml (or to any interpreter).
A really useful book on functional data structures is Chris Okasaki's Purely Functional Data Structures, which you may be able to take out from the library (or buy, if you're really keen). Although the code examples are in Standard ML, not Ocaml, you can get translations of them to Ocaml from the Ocaml web site here.
A great book for learning about functional programming, geared towards novice programmers, is Abelson and Sussman's Structure and Interpretation of Computer Programs. It uses the Scheme programming language, which is much simpler than Ocaml. The book (available online for free) is a great way to prepare yourself for learning Ocaml. The first two chapters cover functional programming is considerable detail.
Finally, if you become a serious Ocaml programmer, you will probably want to subscribe to one or more of the Ocaml mailing lists.