* Oo.copy
@ 1996-05-25 20:25 ESPERET PHILIPPE
1996-05-28 11:48 ` Oo.copy Jacques GARRIGUE
0 siblings, 1 reply; 5+ messages in thread
From: ESPERET PHILIPPE @ 1996-05-25 20:25 UTC (permalink / raw)
To: liste Caml
% ocaml1.tex 25-5-1996 (23h:16)
%%%%%%%%%%%%%%
Philippe Esperet (France)
Fax : (33-1) 46 56 83 68
email 100060.2106@compuserve.com
I cannot understand how to access a fresh copy of an object with
O'Caml (Oo seems normally to copy only pointers). Thank you if someone
can explain me how to get such a copy (please see below for an example).
One related problem is : the documentation for O'Caml exists but is not
so thick ; it could be useful to have a list where true beginners in
OCaml might ask their questions and find examples.
(*
#use "C:/OCAML/esperet/email3.ml";;
*)
class virtual 'a matrix(sz,init:int*'a) as self=
val size=sz
val m=Array.create_matrix sz sz init
val zero=init
virtual printa:'a -> unit
(*method copy()=new matrix(size,zero)
forbidden: One cannot create instances of the virtual class matrix*)
method m=m
method set(i,j,nval:int*int*'a)= m.(i).(j) <- nval
method build(f:int->int->'a)=for i=0 to size-1 do
for j=0 to size-1 do
m.(i).(j)<- f i j done done;self
method print()=for i=0 to size-1 do
for j=0 to size-1 do
self#printa m.(i).(j);
print_char ';' done;
print_newline() done
end
class int_matrix (sz:int)=
inherit (int) matrix (sz,0)
method printa=print_int
end
let m=new int_matrix 3;;
(m#build (fun i j->i+j))#print();;
m#print();;
let n=Oo.copy m;;
(*let nn=m#copy();;*)
m#set(1,1,66);;
n#print();;
(*nn#print();;*)
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Oo.copy
1996-05-25 20:25 Oo.copy ESPERET PHILIPPE
@ 1996-05-28 11:48 ` Jacques GARRIGUE
1996-05-28 13:06 ` Oo.copy Didier Remy
0 siblings, 1 reply; 5+ messages in thread
From: Jacques GARRIGUE @ 1996-05-28 11:48 UTC (permalink / raw)
To: 100060.2106; +Cc: caml-list
>>>>> ESPERET PHILIPPE <100060.2106@compuserve.com> writes:
> I cannot understand how to access a fresh copy of an object with
> O'Caml (Oo seems normally to copy only pointers). Thank you if someone
> can explain me how to get such a copy (please see below for an example).
> One related problem is : the documentation for O'Caml exists but is not
> so thick ; it could be useful to have a list where true beginners in
> OCaml might ask their questions and find examples.
> class virtual 'a matrix(sz,init:int*'a) as self=
> val size=sz
> val m=Array.create_matrix sz sz init
> val zero=init
> virtual printa:'a -> unit
> (*method copy()=new matrix(size,zero)
> forbidden: One cannot create instances of the virtual class matrix*)
> method m=m
> method set(i,j,nval:int*int*'a)= m.(i).(j) <- nval
> method build(f:int->int->'a)=for i=0 to size-1 do
> for j=0 to size-1 do
> m.(i).(j)<- f i j done done;self
> method print()=for i=0 to size-1 do
> for j=0 to size-1 do
> self#printa m.(i).(j);
> print_char ';' done;
> print_newline() done
> end
> class int_matrix (sz:int)=
> inherit (int) matrix (sz,0)
> method printa=print_int
> end
> let m=new int_matrix 3;;
> (m#build (fun i j->i+j))#print();;
> m#print();;
0;1;2;
1;2;3;
2;3;4;
> let n=Oo.copy m;;
> (*let nn=m#copy();;*)
> m#set(1,1,66);;
> n#print();;
> (*nn#print();;*)
0;1;2;
1;66;3;
2;3;4;
The problem is that your array is shared between the two copies.
There are various specific ways to solve it.
One is to add an "unsharing" method in the virtual class, which is
applied after copying.
val mutable m = ...
method unshare = m <- Array.map Array.copy m
method copy = let o = Oo.copy m in o#unshare; o
Then the problem is solved by using
> let n = m#copy;;
This is difficult to have a general way, since mutable data structures
can get various forms.
Jacques
---------------------------------------------------------------------------
Jacques Garrigue Kyoto University garrigue@kurims.kyoto-u.ac.jp
<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Oo.copy
1996-05-28 11:48 ` Oo.copy Jacques GARRIGUE
@ 1996-05-28 13:06 ` Didier Remy
0 siblings, 0 replies; 5+ messages in thread
From: Didier Remy @ 1996-05-28 13:06 UTC (permalink / raw)
To: Jacques GARRIGUE; +Cc: 100060.2106, caml-list
> The problem is that your array is shared between the two copies.
> There are various specific ways to solve it.
> One is to add an "unsharing" method in the virtual class, which is
> applied after copying.
>
> val mutable m = ...
> method unshare = m <- Array.map Array.copy m
> method copy = let o = Oo.copy m in o#unshare; o
>
> Then the problem is solved by using
> > let n = m#copy;;
A shorter way is
val m = ...
method copy = {< m = Array.map Array.copy m >}
This is also safer since the state m does not need to be mutable.
> This is difficult to have a general way, since mutable data structures
> can get various forms.
As you have understood, the function Oo.copy implements a superficial copy.
It would be possible to provide a (system) deep copy that would duplicate
the whole graph structure in the memory, using a mechanism similar the
implementation of export and import but not failing on functions. This copy
could also work for any ML value, not just objects. However, it is not clear
that this is often what the user wants, and we did not provide it.
Superficial and deep copy can be polymorphic other all objects and therefore
provided in a (system) library.
Any intermediate copy is arbitrary and therefore should be programmed by the
user, usually as a method of the corresponding objects.
Didier.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Oo.copy
1996-05-28 18:43 Oo.copy Andrew Conway
@ 1996-05-29 1:53 ` Jacques GARRIGUE
0 siblings, 0 replies; 5+ messages in thread
From: Jacques GARRIGUE @ 1996-05-29 1:53 UTC (permalink / raw)
To: caml-list
>>>>> "Andrew" == Andrew Conway <arc@wildtype.Stanford.EDU> writes:
>> From: Jacques GARRIGUE <garrigue@kurims.kyoto-u.ac.jp>
>>
>>>>>>> ESPERET PHILIPPE <100060.2106@compuserve.com> writes:
>>
>> > I cannot understand how to access a fresh copy of an object with
>> > O'Caml (Oo seems normally to copy only pointers). Thank you if someone
>> > can explain me how to get such a copy (please see below for an example).
>>
>> > [ gives example of a class where a mutable element of the class
>> > (an array) is not copied by OO.copy ]
>>
>> The problem is that your array is shared between the two copies.
>> There are various specific ways to solve it.
Andrew> I think that is a bad feature. I realise it may be unavoidable.
Andrew> In particular, when I read the documentation for OO.copy, I assumed
Andrew> that it was a function that descended the data structure, copying
Andrew> all mutable structures. This seemed like a very useful thing to me
Andrew> (and I wish it was available for any given type, not just classes).
Andrew> I can immagine that this is impractical due to the overhead involved
Andrew> in building specific "deep" copy functions for each data type defined
Andrew> (that could possibly contain a mutable data structure), unless the
Andrew> GC information contains enough of a specification to write a general
Andrew> copy function similar to the general comparison functions. This would perhaps
Andrew> only take one bit per block...saying whether the particular block
Andrew> is mutable or not. On the other hand, I do realise that bits are
expensive.
It's not even clear what should be considered as mutable. For
instance, strings are mutable, but most often you would expect deep
copy to copy them. And what should you do about hashtables, etc...
In fact, there is a way to build a general deep copy, if you don't
care about how expensive it is: use the Obj module (about physical
objects, not Oo), and read C headers.
open Obj
let deep_copy (x : 'a) : 'a =
let copied = ref [] in
let rec copy_obj x =
if is_block x & (tag x < 249 or tag x = 252 or tag x = 254) then
try List.assq x in:!copied
with Not_found ->
let x' = new_block (tag x) (size x) in
for i = 0 to size x - 1 do set_field x' i (field x i) done;
copied := (x,x') :: !copied;
for i = 0 to size x' - 1 do
let y = copy_obj (field x' i) in
if y != field x' i then set_field x' i y
done;
x'
else x
in magic (copy_obj (repr x))
This is quite violent, but should work in most cases. Sharing is
preserved. You can extend it to give a list of objects you want to
leave shared with the original.
>> One is to add an "unsharing" method in the virtual class, which is
>> applied after copying.
Andrew> Ugh!
Didier gave a cleaner way to do it. I didn't read the formal
definition for classes...
Jacques
---------------------------------------------------------------------------
Jacques Garrigue Kyoto University garrigue@kurims.kyoto-u.ac.jp
<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Oo.copy
@ 1996-05-28 18:43 Andrew Conway
1996-05-29 1:53 ` Oo.copy Jacques GARRIGUE
0 siblings, 1 reply; 5+ messages in thread
From: Andrew Conway @ 1996-05-28 18:43 UTC (permalink / raw)
To: 100060.2106, garrigue; +Cc: caml-list
>From: Jacques GARRIGUE <garrigue@kurims.kyoto-u.ac.jp>
>
>>>>>> ESPERET PHILIPPE <100060.2106@compuserve.com> writes:
>
> > I cannot understand how to access a fresh copy of an object with
> > O'Caml (Oo seems normally to copy only pointers). Thank you if someone
> > can explain me how to get such a copy (please see below for an example).
>
> > [ gives example of a class where a mutable element of the class
> > (an array) is not copied by OO.copy ]
>
>The problem is that your array is shared between the two copies.
>There are various specific ways to solve it.
I think that is a bad feature. I realise it may be unavoidable.
In particular, when I read the documentation for OO.copy, I assumed
that it was a function that descended the data structure, copying
all mutable structures. This seemed like a very useful thing to me
(and I wish it was available for any given type, not just classes).
I can immagine that this is impractical due to the overhead involved
in building specific "deep" copy functions for each data type defined
(that could possibly contain a mutable data structure), unless the
GC information contains enough of a specification to write a general
copy function similar to the general comparison functions. This would perhaps
only take one bit per block...saying whether the particular block
is mutable or not. On the other hand, I do realise that bits are expensive.
>One is to add an "unsharing" method in the virtual class, which is
>applied after copying.
Ugh!
> ...
>
>This is difficult to have a general way, since mutable data structures
>can get various forms.
Agreed.
Andrew.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~1996-05-29 10:02 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-05-25 20:25 Oo.copy ESPERET PHILIPPE
1996-05-28 11:48 ` Oo.copy Jacques GARRIGUE
1996-05-28 13:06 ` Oo.copy Didier Remy
1996-05-28 18:43 Oo.copy Andrew Conway
1996-05-29 1:53 ` Oo.copy Jacques GARRIGUE
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox