From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Delivered-To: caml-list@yquem.inria.fr Received: from nez-perce.inria.fr (nez-perce.inria.fr [192.93.2.78]) by yquem.inria.fr (Postfix) with ESMTP id D42A7BC32 for ; Wed, 16 Mar 2005 01:18:24 +0100 (CET) Received: from pauillac.inria.fr (pauillac.inria.fr [128.93.11.35]) by nez-perce.inria.fr (8.13.0/8.13.0) with ESMTP id j2G0IOi9001223 for ; Wed, 16 Mar 2005 01:18:24 +0100 Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id BAA29284 for ; Wed, 16 Mar 2005 01:18:24 +0100 (MET) Received: from first.in-berlin.de (dialin-145-254-052-221.arcor-ip.net [145.254.52.221]) by concorde.inria.fr (8.13.0/8.13.0) with ESMTP id j2G0IMCI022102 for ; Wed, 16 Mar 2005 01:18:22 +0100 Received: by first.in-berlin.de (Postfix, from userid 501) id D72F0BBCC2; Wed, 16 Mar 2005 01:18:19 +0100 (CET) Date: Wed, 16 Mar 2005 01:18:19 +0100 From: Oliver Bandel To: caml-list@inria.fr Subject: Re: [Caml-list] OCaml troll on Slashdot Message-ID: <20050316001819.GB347@first.in-berlin.de> References: <42363A86.6010309@1969.ws> <200503150859.55997.jon@ffconsultancy.com> <200503152036.45894.jon@ffconsultancy.com> <32977.131.254.50.45.1110920621.squirrel@mail.irisa.fr> <172f01077499b3d417604d0ad31f2bdb@cs.unm.edu> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <172f01077499b3d417604d0ad31f2bdb@cs.unm.edu> User-Agent: Mutt/1.5.6i X-Miltered: at nez-perce with ID 42377B50.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Miltered: at concorde with ID 42377B4E.000 by Joe's j-chkmail (http://j-chkmail.ensmp.fr)! X-Spam: no; 0.00; oliver:01 bandel:01 oliver:01 in-berlin:01 caml-list:01 ocaml:01 inherently:01 arrays:01 toplevel:01 ocamlprof:01 rec:01 memoized:01 memoize:01 recursive:01 rec:01 X-Spam-Checker-Version: SpamAssassin 3.0.2 (2004-11-16) on yquem.inria.fr X-Spam-Status: No, score=0.1 required=5.0 tests=FORGED_RCVD_HELO autolearn=disabled version=3.0.2 X-Spam-Level: On Tue, Mar 15, 2005 at 04:07:37PM -0700, William D.Neumann wrote: > On Mar 15, 2005, at 3:12 PM, Yoann Padioleau wrote: > > >>To which, I'd assume the majority response would be, "So?" > > > >So some of his arguments are right. You make object "So?" but > >we could continue a long moment that way. > > Perhaps, perhaps not. His point seems to be that programming in a > "functional style"[1] is inherently slower than an imperative style > because a list or a map have different performance characteristics than > do arrays. To which the only response is along the lines of "True. Well, I tested the program with the original values for columnSize and numRows as well as differet values. I did not used the values that are mentioned in the posting (7x3), because I had not too much time. But with let columnSize = 5;; and with let numRows = 7;; (look at the ";;" it seems he had used it in the toplevel... :)) and ocamlprof I got stuff like that: ================================================ (* checks if each cell in center colum is covered by an empty cell *) let rec isCovered c1 c2 c3 = (* 2650588 *) let memoized_isCovered = memoize3 isCovered_table isCovered in match (c1, c2, c3) with (* if center runs out of cells first, we are covered *) | (_, [], _) -> (* 501290 *) true (* if others run out first, we are not covered *) | ([], _, _) -> (* 0 *) false | (_, _, []) -> (* 0 *) false (* Empty followed by Planted in center colum skip this cell and next cell *) | ( (_::(_::rest1)), (Empty::(Planted::rest2)), (_::(_::rest3)) ) -> (* 553730 *) true && ( isCovered rest1 rest2 rest3 ) | ( (Empty::rest1), (_::rest2), (_::rest3) ) -> (* 837698 *) true && ( isCovered rest1 rest2 rest3 ) | ( (_::rest1), (_::rest2), (Empty::rest3) ) -> (* 291720 *) true && ( isCovered rest1 rest2 rest3 ) (* Empty followed by Empty in center This cell is covered, but don't skip next cell *) | ( (_::rest1), (Empty::rest2), (_::rest3) ) -> (* 297530 *) true && ( isCovered rest1 rest2 rest3 ) (* this cell is covered by next cell *) | ( (_::rest1), (Planted::(Empty::rest2)), (_::rest3) ) -> (* 99282 *) true && ( isCovered rest1 (Empty::rest2) rest3 ) (* default: we reach this if our current cell is not covered *) | (_, _, _) -> (* 69338 *) false;; ================================================ which does not really looks tail recursive. Called more than 2 * 10^6 times... And many other examples... e.g. this one: (* applies a list of functions to an argument *) let rec applyFunctionList functions argument = (* 267386 *) match functions with | [] -> (* 9782 *) [] | f::rest -> (* 257604 *) (f argument)::(applyFunctionList rest argument);; "only" called 267386 times, but when looking how the arguments are used: also applyFunctionList is not tail recursive... ...and even if called less than 10^6 times... it's a function that creates a list in a non-tailrec way. IMHO this is the reason, why the program performs so badly! Ths stuff of tail recursion - even if it took a while until I got it - was one of the first things on this list, that people told me that it is necessary.... ...but as a *real* C++ programmer it seems it is not necessary to learn... ...and better use the energy to tell all people how badly OCaml performs! Well... he performs badly in code-writing. :-> If he had read this mailing list, he wouls have seen that HE (better: the code he wrote) is/was the problem, not OCaml itself. :) Ciao, Oliver