Browse thread
OCaml troll on Slashdot
-
Karl Zilles
-
Oliver Bandel
-
Michael Vanier
-
Jon Harrop
-
Yoann Padioleau
- Jon Harrop
- Paul Argentoff
- Paul Argentoff
-
Yoann Padioleau
-
Jon Harrop
- Yoann Padioleau
-
Michael Vanier
- Richard Jones
-
Oliver Bandel
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Oliver Bandel <oliver@f...> |
| Subject: | Re: [Caml-list] OCaml troll on Slashdot |
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