List Info

Thread: "ocaml_beginners"::[] How to reuse code ?




"ocaml_beginners"::[] How to reuse code ?
country flaguser name
United States
2007-02-09 16:32:39

Hi OCaml programmers !

Coming from C++ beginner, I try to forget - for a time - oo use and
to focus on modules.

I hope to reuse "show_array"; code :

let show_array the_array print_function =
Array.iteri (fun i x -> print_int i; print_char 't';
print_function x; print_char 'n')
the_array

let show_complex c = print_char '(' ;
print_float c.Complex.re ; print_string ",t";
print_float c.Complex.im; print_char ')'

let () = show_array a_complex_array show_complex;
show_array (Array.map Complex.norm a_complex_array)
print_float

Maybe it would be possible to mimic C++ and to forge a base class
for show_array parameter : deriving a complex and simple float from it.

But please, how to avoid to explicitly pass the print function to
";show_array" without using the oo features of OCaml ?

Thanks for your help.

Fabrice.
--
I wonder if these naughty spammers that attack Caml-list these days
use "polygen" with a slightly modified grammar from "pornsite.grm" ?

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
United States
2007-02-09 16:58:14

fabrice.marchant wrote:
> But please, how to avoid to explicitly pass the print function to
> "show_array"; without using the oo features of OCaml ?

If you had a library of functions that all worked on a given type, you
could use functors. But for a single function, passing the printer as a
parameter is exactly what you'd do. Then you can use partial evaluation
to make it look nice:

let a_complex_array = [|Complex.zero; Complex.one|]

(* note that print_array takes two parameters through we're only
declaring one explicitly *)

let print_array print_function =
Array.iteri (fun i x ->
print_int i;
print_char 't';
print_function x;
print_char 'n')

let print_complex c =
print_char '(' ;
print_float c.Complex.re;
print_string ",t";
print_float c.Complex.im;
print_char ')'

let print_complex_array = print_array print_complex
let print_float_array = print_array print_float

let () =
print_complex_array a_complex_array;
print_float_array (Array.map Complex.norm a_complex_array)

If, however, you're trying to write a generic function to dump generic
ocaml datastructures, the problem is much harder, since ocaml doesn't
keep type information with the variables. There has been some useful
code posted to this list that does a good job for what it has to work with.

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
United States
2007-02-09 17:21:31

On Fri, 9 Feb 2007, fabrice.marchant wrote:

> Hi OCaml programmers !
>
> Coming from C++ beginner, I try to forget - for a time - oo use and
> to focus on modules.

Hi,

You really should use the printf family of functions from the Printf
module or from the Format module.

> I hope to reuse "show_array"; code :
>
> let show_array the_array print_function =
> Array.iteri (fun i x -> print_int i; print_char 't';
>; print_function x; print_char 'n')
>; the_array

Here is what I would write:

open Printf

let show_array oc f a =
Array.iteri (fun i x -> fprintf oc "%it%an" i f x) a

oc is the out_channel, which you can set to stdout if you want.
The order of the arguments of show_array and of f are such that they can
be used with fprintf or printf.

If you need pretty-printing, you can use the Format module. It's a bit
more complicated though. However it's more polymorphic since the output is
performed to an abstract formatter, which may be write to a channel or a
character buffer, rather than only out_channels.

> let show_complex c = print_char '(' ;
> print_float c.Complex.re ; print_string ",t";
>; print_float c.Complex.im; print_char ')'

let show_complex oc c =
fprintf oc "(%10.6f,%10.6f)" c.Complex.re c.Complex.im

Note that I remove the tabs, which are almost always a bad solution.

> let () = show_array a_complex_array show_complex;
> show_array (Array.map Complex.norm a_complex_array)
> print_float

let () =
show_array stdout show_complex a_complex_array;
show_array stdout
(fun oc x -> fprintf oc "%10.6f" x)
(Array.map Complex.norm a_complex_array);;

> Maybe it would be possible to mimic C++ and to forge a base class
> for show_array parameter : deriving a complex and simple float from it.
>
> But please, how to avoid to explicitly pass the print function to
> "show_array"; without using the oo features of OCaml ?

let print_array = show_array stdout print_function

Martin

--
Martin Jambon
http://martin.jambon.free.fr

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
France
2007-02-10 09:25:12

Karl and Martin, thanks !

I'll remember about "partial evaluation" :
> let print_complex_array = print_array print_complex

> ...to write a generic function to dump generic
> ocaml datastructures, the problem is much harder, since ocaml doesn't
> keep type information with the variables. There has been some useful
> code posted to this list that does a good job for what it has to work
>; with.

I'm very interested in reading such previous topics. Maybe I have to search
"generic" word ? Please Karl, do you have other clues that could help to
locate them ?

>; Here is what I would write:
>
> open Printf
>
> let show_array oc f a =
> Array.iteri (fun i x -> fprintf oc "%it%an" i f x) a

Thanks, Martin ! Even for a newbie, it's a shame for me to have missed this
mandatory C-like lib...

> > But please, how to avoid to explicitly pass the print function to
> > "show_array"; without using the oo features of OCaml ?
>
> let print_array = show_array stdout print_function
If I understand this, Martin : a kind of partial evaluation,
the thing Karl spoke about ?

Regards

Fabrice

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
United Kingdom
2007-02-10 09:52:55

On Saturday 10 February 2007 15:25, Fabrice Marchant wrote:
> I'm very interested in reading such previous topics. Maybe I have to
> search "generic" word ? Please Karl, do you have other clues that could
> help to locate them ?

Basically, whenever you define or use a type that you're going to want to be
able to convert into string format, you write a string_of_foo function. For
example:

# type pos = {x: int; y:int};;

# let string_of_pos r = Printf.sprintf "(%d, %d)" r.x r.y;;
val string_of_pos : pos -> string = <fun>;

If you have a polymorphic type then your string_of_foo function is a
higher-order function that expects the appropriate string_of_* function for
the type parameter. For example, a string_of_list function will accept a
string_of_elt function to convert each element into a string:

# let string_of_list string_of_elt list =
"[&quot;^String.concat "; " (List.map string_of_elt list)^&quot;]";;
val string_of_list : ('a -> string) -> 'a list -> string = <fun>;

These design patterns in OCaml are covered in my book "OCaml for Scientists".

> > Here is what I would write:
&gt; >
>; > open Printf
&gt; >
>; > let show_array oc f a =
> > Array.iteri (fun i x -> fprintf oc "%it%an" i f x) a
>
> Thanks, Martin ! Even for a newbie, it's a shame for me to have missed this
>; mandatory C-like lib...

I believe there is a thorough discussion in the OCaml manual. Also, fire up
the ocamlbrowser program and look at the documentation for the Printf module.

> > > But please, how to avoid to explicitly pass the print function to
> > > "show_array"; without using the oo features of OCaml ?
> >
>; > let print_array = show_array stdout print_function
>
> If I understand this, Martin : a kind of partial evaluation,
> the thing Karl spoke about ?

Exactly. All function definitions are curried by default in OCaml. So when you
write a function that tries to find an element in a list:

# let rec find f list = match list with
| [] -> raise Not_found
| h::t when f h -> h
| _::t -> find f t;;
val find : ('a -> bool) -> 'a list -> 'a = <fun>;

you can partially apply the "find" function with a function "f&quot; to search for
particular elements. For example, you can create a function to find only even
elements in an int list:

# let find_even = find (fun i -> i mod 2 = 0);;
val find_even : int list -> int = <fun>;

Currying makes for concise code. However, you can get into problems if you try
to mix currying, outer-most definitions and polymorphism.

--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
OCaml for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
United States
2007-02-10 21:50:09

On Sat, 10 Feb 2007, Fabrice Marchant wrote:

>>&gt; But please, how to avoid to explicitly pass the print function to
>&gt;> "show_array"; without using the oo features of OCaml ?
>&gt;
>&gt; let print_array = show_array stdout print_function
> If I understand this, Martin : a kind of partial evaluation,
> the thing Karl spoke about ?

Yes. However the term "partial application" is more appropriate than
"partial evaluation", because it doesn't do anything with the body of the
function (show_array) until all the arguments are passed.

Consider this:

let f x y =
let z = x * x in
x + y

let g = f 2

g is internally organized as a record containing a pointer to the function
(f) and the arguments that have been given already (x = 2).
z is *not* computed when you create g.

It constrasts with:

let f x =
let z = x * x in
fun y -> x + y

Martin

--
Martin Jambon
http://martin.jambon.free.fr

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
France
2007-02-11 06:15:27

Thank you, John and Martin for the explanations and the examples of partial functions ! They are very useful for me.

&gt; "... covered in my book "OCaml for Scientists"
John, I would be glad to buy your book if only I could find it in France.
(But last time I imported something from States - it was a DDJ CD, 8 years ago -, Federal Express claimed then heavy additional taxes or fees that were hidden before...)

Martin, the two contrasting examples you give encourage to be very cautious about OCaml coding : for a same job, I bet the execution speed can be different.

The following example seems to be closely related to the things you explain.
I wanted a function to handle graphics init and exit for a drawing function :

let graphic_main drawing_fun =
open_graph " 800x600&quot;;
drawing_fun ();
set_color foreground;
moveto 0 0; draw_string "'Q' to quit.";;
let keep = ref true in
while !keep do
let e = wait_next_event [Key_pressed] in
if e.keypressed then(
match e.key with
| 'q' | 'Q' -> keep := false
| _ -> ()
)
done;
close_graph()

which was written with a zero parameter function "drawing_fun&quot; in mind.

I was then surprised it was possible to use "graphic_main&quot; with multi parameters functions in adding a dummy one this way :

let three_true_parms_draw_something p1 p2 p3 dum =...

let () = graphic_main (three_true_parm_draws_something 1 2 3)

It compiles and works. However this last parameter seems rather tricky...

Best regards

Fabrice

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
United States
2007-02-13 16:56:11

Fabrice Marchant wrote:
&gt; I'm very interested in reading such previous topics. Maybe I have to search
&gt; "generic" word ? Please Karl, do you have other clues that could help to
> locate them ?

Check out the responses to:

http://tech.groups.yahoo.com/group/ocaml_beginners/message/4816

Perhaps the simplest solution is:

http://merjis.com/developers/dumper

(because of the lack of run-time type information, there is only so much
it can give you, but it can be very helpful even so.)

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
France
2007-02-14 05:42:32

Thank you Karl for the merjis link !

Moreover it brings sources and an interesting tutorial for beginners like me.

Fabrice

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] How to reuse code ?
country flaguser name
United Kingdom
2007-02-14 13:49:23

On Tue, Feb 13, 2007 at 02:56:11PM -0800, Karl Zilles wrote:
&gt; Fabrice Marchant wrote:
&gt; > I'm very interested in reading such previous topics. Maybe I have to search
&gt; > "generic" word ? Please Karl, do you have other clues that could help to
> > locate them ?
>
> Check out the responses to:
>
> http://tech.groups.yahoo.com/group/ocaml_beginners/message/4816
>
> Perhaps the simplest solution is:
>
> http://merjis.com/developers/dumper
&gt;
> (because of the lack of run-time type information, there is only so much
> it can give you, but it can be very helpful even so.)

You might want to note that the latest version of dumper is included
in Extlib (it's called Std.dump).

Rich.

--
Richard Jones
Red Hat UK Limited

__._,_.___
.

__,_._,___
[1-10]

about | contact  Other archives ( Real Estate discussion Medical topics )