Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] productivity improvement
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Oleg <oleg_inconnu@m...>
Subject: Re: [Caml-list] productivity improvement
On Wednesday 10 July 2002 11:39 am, John Max Skaller wrote:
> Oleg wrote:
> >What are the _simplest_ examples that demonstrate considerable (> 2:1)
> > O'Caml vs C++ productivity improvement (in terms of program size) and
> > where can I find them?
>
> Try doing this in C++:
>
>     type 'a node = Leaf of 'a | Unop of ('a->'a) * node | Binop of ('a *
> 'a -> 'a)
>     let rec eval n = match n with
>
>     | Leaf  i -> i
>     | Unop (f,n) -> f (eval n)
>     | Binop (f,n1,n2) -> f ((eval n1), (eval n2))
>
> [Hint: it cannot be done without one of:
>     a) casts, or
>     b) serious difficulties wth memory management
> ]

Shame on you! I hear you are on the C++ standardization committee :)
Code first [1], comments below.

<C++>
    1   #include <iostream>
    2   #include <cmath>
    3
    4   template<class T>
    5   struct node { 
    6       virtual T eval() = 0;
    7   };
    8
    9   template<class T>
   10   struct leaf : public node<T> {
   11       T i;
   12       T eval() { return i; }
   13       leaf(const T& t) : i(t) {};
   14   };
   15
   16   template<class T>
   17   struct unop : public node<T> {
   18       T (*fun)(T);
   19       node<T>& n;
   20       T eval() { return fun(n.eval()); }
   21       unop(T (*f)(T), node<T>& N) : fun(f), n(N) {}
   22   };
   23
   24   template<class T>
   25   struct binop : public node<T> {
   26       T (*fun)(T, T);
   27       node<T> &n1;
   28       node<T> &n2;
   29       T eval() { return fun(n1.eval(), n2.eval()); }
   30       binop(T (*f)(T, T), node<T>& N1, node<T>& N2) : fun(f), n1(N1), 
n2(N2) {}
   31   };
   32
   33   int main() {
   34       typedef node<double> N;
   35       typedef leaf<double> L;
   36       typedef unop<double> U;
   37       typedef binop<double> B;
   38       L a(4);
   39       U b(std::sin, a);
   39       U b(std::sin, a);
   40       U c(std::cos, a);
   41       B d(std::atan2, b, c);
   42       std::cout << d.eval() << '\n';
   43   }
</C++>

As one can see, the code is reasonably idiomatic C++, there are no casts or 
explicit memory management. Templates are used only for genericity. If one 
looks past the superficial syntax differences, the C++ code is not even much 
more verbal than the O'Caml example, namely:

1) one needs to define the abstract (interface) class instead of O'Caml's 
succinct "type 'a node = ".
2) writing "template<class T>", "struct", ": public node<T>", "};" adds to 
program size, while decreasing readability and compilation speed. But writing 
these really happens without much thinking.
3) constructors do have to be written manually, but that's only 3 LOC total 
(1 per each derived class / variant), and they are very simple and idiomatic.
4) as used in "main()", the C++ code will not take any "abstraction" [2]
performance pentalty

John's example was still very interesting [3], thanks: we've learned that 
O'Caml variant types translate into C++ single inheritance from abstract 
classes, not unions. Give me more! 

Best regards,
Oleg

P.S. What I do like about C++, is that even though the language claims to be 
multi-paradigm, good design is really class-based (structs are classes), 
while in O'Caml one has to decide on using classes vs records + HOFs, and 
lists vs arrays vs bigarrays. IMHO maybe O'Caml needs fewer types.

[1] I'm no language lawyer, but I think this is 100% ANSI/ISO C++. BTW, it 
compiled with "g++-3.0 -pedantic" without warnings or errors.

[2] In C terms, "calling function through a pointer" in node<double>'s 
virtual table. There will be no penalty, because the C++ compiler is required 
to infer types at compile time here. How about O'Caml? Will it do "match" at 
compile time, if possible?

[3] Special Simpsons quote today:
KITENGE: This is the earliest known fossil of a human being. It's over two 
million years old. 
HOMER: Pff, I've got more bones than that guy. If you're trying to impress 
me, you've failed.
KITENGE: It's not the number of bones, sir, it's the...
HOMER: You have failed!
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners