caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* initialization of arrays
@ 1997-04-29 20:08 David Monniaux
  1997-05-05 17:06 ` Pierre Weis
  1997-05-06 11:43 ` Christophe Raffalli
  0 siblings, 2 replies; 3+ messages in thread
From: David Monniaux @ 1997-04-29 20:08 UTC (permalink / raw)
  To: Caml-list

[en français: l'initialisation de tableaux n'est pas pratique pour les
types mutables...]

Hi,

creating an array initializes all the cells to the same physical content.
That is not very handy when the content is a mutable record. Of course,
one can initialize the cells with copies of a given record. There we run
into another problem: the only way I know of, given a record, produce
another record of the same content, is to write the following kind of
code:
{ field1=a.field1; field2=a.field2 ...}
This is quite cumbersome.

Wouldn't it be handy to have a function of type 'a->'a that duplicates
physically a piece of data, and functions that create vectors or
matrices with copy?

I feel it's now doable somehow with the Obj module (I'm testing it), but
using undocumented features is cumbersome and unsafe...

Thanks.






^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: initialization of arrays
  1997-04-29 20:08 initialization of arrays David Monniaux
@ 1997-05-05 17:06 ` Pierre Weis
  1997-05-06 11:43 ` Christophe Raffalli
  1 sibling, 0 replies; 3+ messages in thread
From: Pierre Weis @ 1997-05-05 17:06 UTC (permalink / raw)
  To: David Monniaux; +Cc: caml-list

> [en français: l'initialisation de tableaux n'est pas pratique pour les
> types mutables...]

[en français: il faut initialiser les tableaux avec des fonctions
d'initialisation appele'es pour chaque e'le'ment du tableau...]

> Hi,
> 
> creating an array initializes all the cells to the same physical content.

Yes, since the name ``Array'' is a bit cheating in Caml: there are no
arrays, just flat vectors. Arrays are incoded into these flat vectors
as vectors having vectors as elements (hence this strange
'a array array type for a matrix). That's why a naive definition of a
matrix (Array.create n (Array.create m 0)) leads to the unexpected
sharing of the matrix's rows.

> That is not very handy when the content is a mutable record. Of course,
> one can initialize the cells with copies of a given record. There we run
> into another problem: the only way I know of, given a record, produce
> another record of the same content, is to write the following kind of
> code:
> { field1=a.field1; field2=a.field2 ...}

> This is quite cumbersome.

Yes it is, but you need not to use this kind of ``by hand'' copy. You
should instead define a copying function for your records:
let copy_record { field1=a1; field2=a2 ...} = { field1=a1; field2=a2...};;

You then have to use a functional initialisation of your
array, using an explicit function argument to initialize items:

(* val init_array : int -> (int -> 'a) -> 'a = <fun> *)
let init_array n f =
 if n = 0 then [||] else
 let val0 = f 0 in
 let v = Array.create n val0 in
 for i = 1 to n - 1 do
  v.(i) <- f i
 done;
 v;;

You then use

# let arr = init_array 10 (function i -> i);;
val arr : int array = [|0; 1; 2; 3; 4; 5; 6; 7; 8; 9|]

to get a vector initialized with given integers.

In the same vein, you may also initialize a matrix:

# let mat = init_array 5 (function i -> init_array 5 (function j -> i + j));;
val mat : int array array =
  [|[|0; 1; 2; 3; 4|]; [|1; 2; 3; 4; 5|]; [|2; 3; 4; 5; 6|];
    [|3; 4; 5; 6; 7|]; [|4; 5; 6; 7; 8|]|]

In your case, initialisation with a mutable record is just:
 init_array n
  (function i -> init_array m
  (function j -> {field1 = e1; field2 = e2; ...}))

or equivalently
 init_matrix n m (function i -> function j -> {field1 = e1; field2 = e2; ...})

Note that, using the expanded form, you can finely monitor the
sharing. For instance
 init_array n
  (function i -> init_array m
  (let e1 = ... and e2 = ... in
  (function j -> {field1 = e1; field2 = e2; ...})))

means that expressions e1 and e2 will be computed once for each row
(hence their values are shared among elements of a row).

Now copying a matrix with your mutable record values is defined via
the record copying function:
let copy a =
 init_matrix n m (function i -> function j -> copy_record a.(i).(j))

With init_array, a matrix copying function is a one-liner:

(* val shallow_copy_matrix : 'a array array -> 'a array array = <fun> *)
let shallow_copy_matrix a =
  init_array (Array.length a) (function i -> Array.copy a.(i));;

(* copy_matrix : 'a array array -> (int -> int -> 'b) -> 'b array array *)
let copy_matrix a f =
  init_array (Array.length a)
   (function i -> init_array (Array.length a.(i)) (function j -> f i j));;

You may also define a general functional matrix initializer to derive
the copying functions:

(* init_matrix : int -> int -> (int -> int -> 'a) -> 'a array array *)
let init_matrix n m f =
 init_array n (function i -> init_array m (function j -> f i j));;

(* map_matrix : 'a array array -> (int -> int -> 'b) -> 'b array array *)
let map_matrix a f =
 let n = Array.length a in
 if n = 0 then [||] else
 let m = Array.length a.(0) in
 init_matrix n m f;;

let copy_matrix = map_matrix;;

> Wouldn't it be handy to have a function of type 'a->'a that duplicates
> physically a piece of data, and functions that create vectors or
> matrices with copy?

The problem is: how deep will be the copy? If you want the copy
function to handle properly matrix it cannot be a shallow copy. Thus
this copy function will be costy and hard to use. Anyway, copying of
vectors and matrices is really trivial using Array.copy and copy_matrix.

> I feel it's now doable somehow with the Obj module (I'm testing it), but
> using undocumented features is cumbersome and unsafe...

You're right. I guess we could have a Matrix module, defining the same
set of primitives as the Array module for 'a array array values: you
then solve your problem with Matrix.copy, Matrix.create (and other
problems as matrix concatenation, filling or blitting).

> Thanks.

Pierre Weis

INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/







^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: initialization of arrays
  1997-04-29 20:08 initialization of arrays David Monniaux
  1997-05-05 17:06 ` Pierre Weis
@ 1997-05-06 11:43 ` Christophe Raffalli
  1 sibling, 0 replies; 3+ messages in thread
From: Christophe Raffalli @ 1997-05-06 11:43 UTC (permalink / raw)
  To: David.Monniaux; +Cc: caml-list


Hi,

I agree with this, but more generally we need a syntactic sugar to copy a
record and change some fields like

{ r with a = e; b = f; ... }

Or anything like that ! 
(this would give record copy by removing the with part)

When you use a record with many fields it makes the program much longer (and
less readable) when you often need to change one or two field in a record.

----
Christophe Raffalli
Universite Paris XII

URL: http://www.logique.jussieu.fr/www.raffalli




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1997-05-06 12:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-04-29 20:08 initialization of arrays David Monniaux
1997-05-05 17:06 ` Pierre Weis
1997-05-06 11:43 ` Christophe Raffalli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).