An amazing language that I am using on the project I am working on — goanna — is ocaml (pronounce ocamel). It is an implementation of an ML (Meta Language), a functional language based on the theoretical background of the lambda-calculus. The paradigm is different from the one of imperative languages (like java or C) or declarative languages (like XML if we consider it as a declarative one). It has been created originally as a language to implement theorem provers. In the meantime there is a bunch of well known projects that use it, like MLDonkey to cite just one.
That are some of the points I like in that languages.
It is a statically typed languages where all the typing is done at compilation time. A lot of bugs are caught at that moment. There’s no way to produce a segmentation fault or an abort. It saves quite a lot of time in debugging. Once a program can be successfully compiled, there’s a great deal of chance that it will run the way it is supposed to. In all case, no nasty and hard to find bugs about pointers or out of bound arrays. Of course, like in languages such as Java or C#, there is a garbage collector, so no need to do the memory management oneself like in C/C++, hence no memory leaks.
As a functional language, the functions play an important role. The function are said to be first class citizens, they can be passed as parameter to functions, returned by function and so on. For example if I would like to apply some function to every element of a list, we can do it like that (in interactive mode):
#let rec map f list =
match list with
 -> 
| head::tail -> f head :: (map f tail)
val map : ('a -> 'b) -> 'a list -> 'b list = < fun >
# let inc x = x+1;;
val inc : int -> int = < fun >
# let l = [4;5;9];;
val l : int list = [4; 5; 9]
# map inc l;;
- : int list = [5; 6; 10]
The definition of the function map is the following: we define it to be recursive (rec) and to take a function f and a list as parameter. In case that the list is empty (1st match case), it will return an empty list. Otherwise, it will apply the function f to the first element (the head) and do a recursive call of map for the tail (that is also a list, namely the list consisting of all elements of the original one without the first element). The next line is just the type of that function as infered by the system. We see then how the function works with a function inc, which function is obvious, and a list of integer as parameters.
In ML, ocaml in particular, here is how we can store a tree representing real expressions and define a function eval to evaluate recursively such a tree. I find that sooo elegant, as the whole program remains tiny and can be used to store any real expression.
(* define a realexp type *)
(* it can be a float or an expression consisting of a function and 2 subtrees *)
type realexp =
Num of float
| Exp of (float -> float -> float) * realexp * realexp
(* let's define an eval expression to get a float from a realexp tree *)
let rec eval exp =
match exp with
Num n -> n
| Exp (f, op0, op1) -> f (eval op0) (eval op1)
(* define a tree stucture corresponding to some real expression *)
(* namely: (3.5 * 4.5) + (2.5 / 1.1) *)
let exp = Exp ((+.), Exp (( *.), Num 3.5, Num 4.5), Exp ((/.), Num 2.5, Num 1.1))
(* evaluate it *)
let result = eval exp
(* val result : float = 18.0227272727272734 *)
That’s just excellent!