Mauricio Fernandez wrote:
> You can read that as
>  
>  let l = range 1 n in
>    List.fold_left (fun acc _ -> f acc) (List.hd l) (List.tl l)

Oh, of course! The ignored argument is the number 1 .. n.

> Actually, in Ruby 1..n is a Range object which responds to the #inject
> message without creating an intermediate array,

Laziness, yep.

> ...
> class ...

You wouldn't use objects to do this in OCaml though. If you wanted to fold
over a data structure you'd just write:

  let nest n f x = fold (fun x _ -> f x) x {1 .. n}

> Of course, being dynamically typed, Ruby doesn't have/need parameterized
> classes, and instead of using a succ function, Range#each repeatedly calls
> the #succ method of the lower bound.

I don't think parameterized classes are needed here.

If you want it more dynamic (generic over kind of data structure, for
example), you might write:

  let nest n f x = {1 .. n}#fold (fun x _ -> f x) x 

but I've never used this style in practice (you always know what data
structure you're dealing with).

> One last note: while things like #inject are as powerful as their OCaml
> counterparts (and more convenient thanks to dynamic typing, but you know
> there's a price for that...), they are often slower than simpler iteration
> methods:

There is a similar overhead in OCaml (for polymorphic HOFs).

>   # >>                 user     system      total        real
>   # >> each        0.610000   0.000000   0.610000 (  0.618960)
>   # >> inject      1.800000   0.020000   1.820000 (  1.850604)
> (yes, it really is that slow)
> 
> Also, Ruby doesn't optimize tail calls, so you cannot write the sort of
> recursive functions OCaml excels at. OTOH, the core classes provide much
> more functionality, and more often than not the existing higher-order
> functions will fit the bill.

I think this is equivalent:

# let time f x =
    let t = Sys.time() in
    let f_x = f x in
    Printf.printf "Time: %f\n%!" (Sys.time() -. t);
    f_x;;
val time : ('a -> 'b) -> 'a -> 'b = <fun>
# let rec loop n f x = if n>0 then (ignore(f x); loop (n-1) f x);;
val loop : int -> ('a -> 'b) -> 'a -> unit = <fun>
# let a = Array.init 10000 (fun i -> i);;
...
# time (loop 100 (fun a -> Array.fold_left (+) 0 a)) a;;
Time: 0.203969
- : unit = ()

So the interpreted OCaml bytecode is ~6x faster and compiled OCaml is ~260x
faster.

Thanks for all the help!

-- 
Dr Jon D Harrop, Flying Frog Consultancy
The F#.NET Journal
http://www.ffconsultancy.com/products/fsharp_journal/?usenet