English version
Accueil     À propos     Téléchargement     Ressources     Contactez-nous    

Ce site est rarement mis à jour. Pour les informations les plus récentes, rendez-vous sur le nouveau site OCaml à l'adresse ocaml.org.

Browse thread
Re: [Caml-list] Why People Aren't Using OCAML? (was Haskell)
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2001-04-01 (21:09)
From: John Max Skaller <skaller@o...>
Subject: Re: [Caml-list] Why People Aren't Using OCAML? (was Haskell)
wester@ilt.fhg.de wrote:

>But probably I still didn't grasp what the real advantages of
> OCaml compared to C++, Java etc. are. So give me and other OCaml
> beginners some more help to better understand what makes OCaml
> superior compared to these main stream languages.

	Ocaml offers (at least :-) two advantages for elementary
use. The first is a proper concept of union. Here is an Ocaml union
and a use of it:

	type node = 
		| Const of int 
		| Unary of char * node
		| Binary of char * node * node

	(* print expression tree in reverse polish *)
	let rp nd = match nd with
		| Const i -> print_int i
		| Unary (op , arg) -> 
			rp arg  ^ " " print_char op
		| Binary (op, arg1, arg2) ->
			rp arg1 ^ " " ^ rp arg2 ^ " " ^ print_char op

How would you do this in C/C++?

	In C, you _ought_ to use:

	struct node {
		enum { Const_tag, Unary_tag, Binary_tag } tag;
		union {
			int Const;
			struct { char op; node *arg; } Unary;
			struct { char op; node *arg1; node *arg2; } Binary;

To use it, you need to write:

	void rp(node *nd) {
		switch (u.tag) {
		case Const_tag: printf("%d",u.Const); break;
		case Unary_tag: 
			rp(u.Unary.arg); printch(' '); printch(U.Unary.op);
		case Binary_tag: 
			rp(u.Binary.arg1); printch(' ');
			rp(u.Binary.arg2); printch(' '); printch(U.Binary.op);

You might leave out the break, and you might accidentally refer to the
wrong component: you can't make either of these mistakes in Ocaml.
Although not shown, you'd have problems destroying the structure
if you forgot a 'free': Ocaml collects garbage automatically.

The above is the 'correctest' solution in C. It won't work in C++,
however, because unions of constructible types are not allowed.
So you're forced to use inheritance and a dynamic cast, which is
very confusing because there is NO abstraction here, and NO

The second advantage for elementary programming is that functions
are first class values. What this means is that you can define
a function in a scope, and pass the function to some other function,
and when you invoke it the scope is remembered. The thing you are
passing is sometimes called a function _closure_. Here is a simple

	let printit printer = printer () in
	let f x = 
		let a = 1 in
		let p () = print_int a in
		printit p

Here, the printit function just invokes the printing routine 'printer',
which is 'p' in the function 'f'. In passing 'p', the value 'a' is not
forgotten. You can do the equivalent in C++ with functiods: but it 
is VERY messy (and very hard to get the memory management right).
Closures are very powerful. 

You do the 'moral equivalent' of the above in C++ using 
classes .. using about 10 times the number of lines of code, 
and probably destroying locality. Here is an example:

	let p lst = 
		let a = 1 in 
		List.iter (fun x -> print_int (x+a)) lst

In C++:

	struct printer {
		int a;
		printer(int aa) : a(aa) {}
		void operator()(int x); { cout << x + a; }
	void p (list<int> l) {
		int a = 1;
		for_each(lst.begin(), lst,end(), printer(a));

but you have to define the 'struct printer' outside
the 'p' routine, destroying locality. Just try
replacing a triply indexed loop with three invocations
of 'for_each' to see what I mean: STL is a great library,
which is basically useless because functions aren't first
class citizens.

[This particular example has significance to me: I gave up
writing a book on generic programming in C++ when I saw
just how long winded it was to code a triply nested loop
using 'for_each']

John (Max) Skaller, mailto:skaller@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
checkout Vyper http://Vyper.sourceforge.net
download Interscript http://Interscript.sourceforge.net
To unsubscribe, mail caml-list-request@inria.fr.  Archives: http://caml.inria.fr