From: Jon Harrop Date: 2007-05-30T11:10:21+09:00 Subject: Re: Ruby & OCaml (was Re: Underscore) 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 = # 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 = # 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