Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Easy solution in OCaml?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Brian Hurt <brian.hurt@q...>
Subject: Re: [Caml-list] Easy solution in OCaml?
On Fri, 25 Apr 2003, Siegfried Gonzi wrote:

> Hi:
> 
> First off: It is not homework. I am 29 and writing my PhD in physics. 
> Often I am contemplating whether it would be possible to use OCaml in 
> combination with my beloved Bigloo to perform statistical evaluations. I 
> am not sure whether there are any out there who /can/ do this 
> evaluations with OCaml what you normally would do with Matlab. The 
> problem what arises: type system and working against the compiler. In 
> Scheme changing a solution from lets say integer-array to double-array 
> is easy, but in Clean for example you would have to change all your 
> dependencies.

I find that if you're working against the compiler, either a) you haven't 
thought the problem through, b) there's an easy solution you're missing, 
or c) you have a bug.

Converting, at run time, from a list of ints to a list of floats is 
trivial in Ocaml:  just do:

let convert_int_list_to_float_list = List.map float_of_int ;;

A similiar function for arrays using Array.map is easy as well.  Note that 
at run time, you have to go through and transform each element (that's 
what List.map does).  You have to do this in any language, because to the 
machine floats are not ints.  Some languages just hide this from you, but 
you have to do it sooner or later anyways.

> I often skim over the libraries and came to the conclusion: C, C++, 
> OCaml impossible for me to see any elegance; Clean a bit better; 
> Bigloo/Scheme: I am not sure here, because everything looks the same 
> maybe this is cheating, but I think it looks the most elegant and less 
> intimitating from all.
> 

One man's elegance is another man's ugliness.  Got to agree with you about 
the C and C++ libraries, though.

> 
> Rationale: given a list of 12 month.  I would like to calculate the 
> quarterly means and skip any nan. Easy? Yes it is but only on paper and 
> in Scheme:
> 
> e.g: [1,2,4,-1,45,56,45,56,8]
> 
> nan=-1.0
> 
> result: [(1+2+3)/3, (45+56)/2, (45+56+8)/3]

let rec sum3 lst =
    match lst with
        [] -> []
        | a :: b :: c :: t -> 
            let s = (if a >= 0 then a else 0) +
                    (if b >= 0 then b else 0) +
                    (if c >= 0 then c else 0)
            and k = (if a >= 0 then 1 else 0) +
                    (if b >= 0 then 1 else 0) +
                    (if c >= 0 then 1 else 0)
            in
               (* Since we're only dealing with 12 months, it's OK not to
                  be tail recursive *)
               (s/k) :: (sum3 t)
        | _ -> assert false (* list is not a multiple of 3 in length *)

Or you could use List.fold_left and an internal function.  Which has the 
advantage of being parameterizable:

let sumN numElems lst =
    let foldfunc = fun (accum, sum, cnt, tot) elem ->
        if (elem >= 0) then
            if (cnt == numElems) then
                if (tot == 0) then
                    ( ( 0 :: accum ), elem, 1, 1 )
                else
                    ( ( (sum/tot) :: accum ), elem, 1, 1)
            else
                ( accum, sum + elem, cnt + 1, tot + 1 )
        else
            if (cnt == numElems) then
                if (tot == 0) then
                    ( ( 0 :: accum ), 0, 1, 0 )
                else
                    ( ( (sum/tot) :: accum ), 0, 1, 0)
            else
                ( accum, sum, cnt + 1, tot )
    in
    let res = List.fold_left foldfunc ([], 0, 0, 0) lst
    in
    match res with
        (accum, sum, cnt, tot) ->
            if (tot > 0) then
                List.rev ( (sum/tot) :: accum )
            else
                List.rev ( 0 :: accum )
;;


> - why if-then constructs? I think this was called "guards" in Clean? Can 
> I use block-structure instead? I hate blocks ala Python but never mind 
> to use it in Clean's way.

Gaurds can be used in Ocaml as well- at least, we have something called 
(IIRC) gaurds, used in pattern matching.

> - why begin-end constructs? In Scheme begin-end constructs are ordinary, 
> but I find it irritating to use it in OCaml.

Begin/end are generally only used to solve shift/reduce conflicts to 
reduce (dangling elses, and in a few other places).

> - is it possible to give type information for readbility. In Clean I 
> often wroten upon entry of the function:

Yep.  You can either give type information peicemeal, using parens, like:
    let sum (x : int) (y : float) = x + (int_of_float y)
(which says foo takes two parameters- an int and a float), or for the 
whole function:
    let sum : int -> float -> int = fun x y -> x + (int_of_float y)

This is usefull for two reasons, in my experience: sometimes, it lets the 
compiler produce better code (for example, consider the function:
let foo x y = x == y
If you know that x and y will always be integers, doing:
let foo (x:int) (y:int) = x == y
allows the compiler to inline integer equals, rather than calling the 
generic compare function- much faster).

The other use is to nail down annoying type errors.  This lets you tell 
the compiler what type something *should* be, and then see where the type 
errors occur.  But generally, you can just let type inference do it's job, 
for example:

let sum x y = x + (int_of_float y)

gets the right type inferred without effort.

Hope this helps.

Brian


-------------------
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