Wednesday, June 25, 2008

Lingual Dexterity - Objective Caml Overview

Yep, that's right. Objective Caml. Objective Caml is an implementation of the Caml language, that adds some object oriented concepts to make it a multi-paradigm language. I chose Objective Caml because it's currently the language of choice of the course I'm currently taking (Prolog to follow. tee hee). In addition, it's a pretty good language for an introduction to functional programming, despite it's object oriented features.

If you're looking for a good tutorial on the language, you can visit the aptly named http://www.ocaml-tutorial.org. A few highlights of what I find interesting are below. Mind you, an Ocaml expert could probably name off a 100 better things, these are just the ones that stand out in my tiny little brain.

Inferred Types


There's no need to declare types in the Ocaml language, but it's very much a strictly typed language. C# 3.0 is getting closer to this with the var keyword and it's inferred typing, but Ocaml is far more advanced in this area. An example in Ocaml:
let myInteger = 8;;

Which would have a C# equivalent of:
var myInteger = 8;

Obviously the benefit to this is that you're code is far less verbose. On the downside, as a noob Ocaml developer, you end up making educated guesses at the return type of your complex functions. This issue is probably more of a combination of the functional style and the inferred typing however, and you can quickly get used to it. I can imagine it's a breeze for anyone with a functional background or experience with dynamically typed languages.

Recursion Over Lists


Something that probably all good functional languages need to do well is recursion. Ocaml has deep support for recursion over lists. Below is an example of a function that sums integers in a list as it loops through it.

let myList = ["a";"b";"c"];;
let rec recurseList theList = match theList with
| [] -> 0 (*base case, have reached the end of the list*)
| head::tail -> head + (recurseList tail);; (*head is the current item in the recursion, tail is the rest of the list*)

Pattern Matching


This is probably the flagship feature of the language. Ocaml provides a rich pattern matching syntax that allows you to use recursion in place of loops easily, or to work with the custom data types you can declare. It's probably best to describe with an example though.

In this example, the first thing I'm going to do is declare a type that describes a binary tree. The data structure has nodes which can have a left node and a right node, and nodes can be empty. The "*" syntax below is how you define a tuple, which would be the equivalent of a C# Pair, but can be any number of items.

type bst = Node of int * bst * bst | Empty

This doesn't translate well to C#, but essentially what we've done is created a data type called "bst", and it can exist in two states. Either as a Node, which is essentially another data type that is a tuple that has a first position of integer, and a second and third position of bst. The bst can also exist in the state "Empty", which you can think of as null.

Now, where pattern matching comes into play is when I want to recurse over this tree to see it's nodes.

let printNode theBst = match theBst with
| Empty -> print_string "this node is empty"
| Node(value, Empty, Empty) -> print_string "this node has no children"
| Node(value, left, Empty) -> print_string "this node has a left child only"
| Node(value, Empty, right) -> print_string "this node has a right child only"
| Node (value, left, right) -> print_string "this node has two child nodes"
| Node (_,_,_) -> print_string "this node can be anything but Empty"

As you can see, it's a really fancy case statement. The final pattern match is redundant, but I thought I'd put it there so you could see an example of how a kind of "wildcard" pattern matching exists.

High Order Functions


High order functions is another feature that is commonly available in most functional programming languages. Its the ability for a function to take another function as an argument. Here's an example in Ocaml:

let doFunction theFunction theValue = 
theFunction theValue;; (*Execute the given function on the given value*)

let myFunction x = x + 1;; (*This is the function to pass to the high-order function*)

doFunction myFunction 3;;(*Output should be 4*)

This is pretty powerful stuff, as most .NET developers have already seen in C# with delegates and now anonymous functions (which you can do in Ocaml as well.)

Summary


Now, the language is cool and all, but based on my background, I struggle to find good uses of it. I think some of these features I identified point out strengths of the language and could highlight potential uses for it (parsing, lexing, basically pattern matching). The Caml website has a bunch of "successful" applications that show various uses. Some of them make sense to me, others make me think, "you probably could have done that with .NET in like an hour".

This is just the tip of the iceberg of the language, and I'm not sure how useful this is to you all, or how comprehensive this is of a description, but it's helped me sum up my thoughts. I'd love to hear your feeback. I'll follow up with a post on the development environment, project structure and unit testing.

0 comments: