Re: a perplexing difference

Pierre Weis (weis@pauillac.inria.fr)
Mon, 24 Jun 1996 21:29:34 +0200 (MET DST)

From: Pierre Weis <weis@pauillac.inria.fr>
Message-Id: <199606241929.VAA19495@pauillac.inria.fr>
Subject: Re: a perplexing difference
To: goffinet@cit-novell.univ-st-etienne.fr (Goffinet)
Date: Mon, 24 Jun 1996 21:29:34 +0200 (MET DST)
In-Reply-To: <1.5.4.16.19960623172313.130f404e@cit-novell.univ-st-etienne.fr> from "Goffinet" at Jun 23, 96 06:01:53 pm

> I'm unable to understand why my fonctions do return these answers

The overall problem is that you misunderstood the Caml notion of
vector (which is the one commonly used in programming languages such as Pascal,
C, Ada, ...): a vector is a mutable data structure, that is,
modification are performed in place. In other words, when you change
the contents of some element in a vector the vector remains the same.
So you cannot get a trace of successive assignments of a vector, unless
you require explicit copies of the vector. This is not common in
practice, since this is memory consuming. In your case, you may want
the computational behaviour of lists and have made a confusion between
vectors and lists (replacements in lists instead of assignments in
vectors, accesses in list instead of direct accesses in vectors, and
so on) ?

> (* first a vect swapping function*)
> let swap k t=
> let prov=t.(k-1) in
> t.(k-1)<-t.(k);t.(k)<-prov;
> t
> ;;

Warning: swap is a procedure, it has not to return something. In your
case returning t is useless, since t is exactly (physically) the same
as the argument of the procedure. Thus as far as mathematical
computation is concerned swap is the identity function on vectors
(more exactely, swap is equivalent to fun k t -> t)

> (*and as I was doubting of everithing I even tried it!*)
> let b=swap 3 [|1;2;3;4;5;6|];;
> let c=swap 1 b;;
> b;;

In particular here, b and c are identical: what you observe when
looking at c is not the new value of b, it's b that has been modified:
#c == b;;
- : bool = true

> (*then an iterator which gives a list of the running results : as with the
> Mathematica FoldList*)
> let rec fold_list f l a=match l with
> []->[a]
> |p::q->a::fold_list f q (f p a);;

This fold_list is a ``memo'' version of the list_it iterator: it
returns the list of successive results of the application of list_it.
#list_it;;
- : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b = <fun>
fold_list : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b list = <fun>

> (* first a test with an ordinary function, then another with swap:
> the first one does what I expected it would,
> the other one yields four times the same list*)
>
> let h u v=u+10*v;;
> fold_list h [5;6;7] 0;;
#fold_list h [5;6;7] 0;;
- : int list = [0; 5; 56; 567]

> fold_list swap [1;3;2] [|10;20;30;40;50|];;

Applied to swap, fold_list returns a list of elements which are
successive results of swap applied to the vector [|10;20;30;40;50|]
given as argument: that's a list of vectors physically equal to the
input argument.

#let orig = [|10;20;30;40;50|];;
orig : int vect = [|10; 20; 30; 40; 50|]

#let [v1; v2; v3; v4] = fold_list swap [1;3;2] orig;;
Entrée interactive:
>let [v1; v2; v3; v4] = fold_list swap [1;3;2] [|10;20;30;40;50|];;
>^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Attention: ce filtrage n'est pas exhaustif.
v1 : int vect = [|20; 40; 10; 30; 50|]
v2 : int vect = [|20; 40; 10; 30; 50|]
v3 : int vect = [|20; 40; 10; 30; 50|]
v4 : int vect = [|20; 40; 10; 30; 50|]
#orig == v1 && v1 == v2 && v2 == v3 && v3 == v4;;
- : bool = true

> (* so I made another swap_like function, I tried, It works*)
> let h x t=[|-x+t.(1);t.(0)|];;

As you may guess, here your h function returns a fresh vector at each
call, hence the copying behaviour you wanted.

> fold_list h [1;3;2] [|10;20;30;40;50|];;
>
> I also tried to Nest my swaps on the command line (with several ((...)))): I
> got the fold_list I expected (and not the constant one)

I don't get this one: if you evaluate (swap 1 (swap 3 (swap 2 orig)))
you will perform the side effect and get orig, but won't get the list
of sucessive states of vector orig. As if we build it by evaluating an
expression equivalent to the call to fold_list, for instance
let v1 = swap 2 orig in
let v2 = swap 3 orig in
let v3 = swap 1 orig in
[v3; v2; v1; orig];;
will return the same list of 4 vectors identical to orig.

> As always, more than an answer, a reference to some place in the
> caml books where I might have found the answer would be welcomed.

I don't know this place.

Well, now you may find it in the caml mailing list archive! :)

Pierre Weis

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