* [Caml-list] Question about objects and method overriding
@ 2014-02-02 11:55 Tom Ridge
2014-02-02 12:43 ` Jacques Garrigue
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Tom Ridge @ 2014-02-02 11:55 UTC (permalink / raw)
To: caml-list
Dear caml-list,
With records, one can functionally update a field e.g. as
{ r with some_field=new_value }
And new_value may, of course, be a function.
With objects, is there similar functionality? e.g. can I write something like
{{ myobj with method some_method=new_method }}
?
Of course, I could copy the methods from myobj explicitly into a new
object (and set some_method to new_method), but I might not know all
the methods available on myobj, and even if I do this becomes
textually extremely verbose.
Of course, new_method cannot directly refer to self etc. Basically I
am using objects in a similar way to records, and would like to use
this functional record update feature.
Thanks
Tom
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-02 11:55 [Caml-list] Question about objects and method overriding Tom Ridge
@ 2014-02-02 12:43 ` Jacques Garrigue
2014-02-02 12:50 ` Tom Ridge
2014-02-03 10:35 ` Goswin von Brederlow
2014-02-05 18:22 ` remy
2 siblings, 1 reply; 9+ messages in thread
From: Jacques Garrigue @ 2014-02-02 12:43 UTC (permalink / raw)
To: Tom Ridge; +Cc: OCaml Mailing List
On 2014/02/02 20:55, Tom Ridge wrote:
> Dear caml-list,
>
> With records, one can functionally update a field e.g. as
>
> { r with some_field=new_value }
>
> And new_value may, of course, be a function.
>
> With objects, is there similar functionality? e.g. can I write something like
>
> {{ myobj with method some_method=new_method }}
>
> ?
>
> Of course, I could copy the methods from myobj explicitly into a new
> object (and set some_method to new_method), but I might not know all
> the methods available on myobj, and even if I do this becomes
> textually extremely verbose.
>
> Of course, new_method cannot directly refer to self etc. Basically I
> am using objects in a similar way to records, and would like to use
> this functional record update feature.
>
> Thanks
>
> Tom
You can copy an object updating a value field, not a method field:
class point (x:int) = object val x = x method get = x method bump dx = {< x = x+dx >} end
You can use this for methods too, by having them call a function value field.
However, this kind of update is only available inside methods, which requires some thinking
when designing your code.
I agree that what you suggest would be nice to have.
There is no majore technical difficulty, but there would be some overhead.
Jacques Garrigue
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-02 12:43 ` Jacques Garrigue
@ 2014-02-02 12:50 ` Tom Ridge
0 siblings, 0 replies; 9+ messages in thread
From: Tom Ridge @ 2014-02-02 12:50 UTC (permalink / raw)
To: Jacques Garrigue; +Cc: OCaml Mailing List
Thanks, that is what I feared. Added as feature request:
http://caml.inria.fr/mantis/view.php?id=6314
On 2 February 2014 12:43, Jacques Garrigue <garrigue@math.nagoya-u.ac.jp> wrote:
> On 2014/02/02 20:55, Tom Ridge wrote:
>
>> Dear caml-list,
>>
>> With records, one can functionally update a field e.g. as
>>
>> { r with some_field=new_value }
>>
>> And new_value may, of course, be a function.
>>
>> With objects, is there similar functionality? e.g. can I write something like
>>
>> {{ myobj with method some_method=new_method }}
>>
>> ?
>>
>> Of course, I could copy the methods from myobj explicitly into a new
>> object (and set some_method to new_method), but I might not know all
>> the methods available on myobj, and even if I do this becomes
>> textually extremely verbose.
>>
>> Of course, new_method cannot directly refer to self etc. Basically I
>> am using objects in a similar way to records, and would like to use
>> this functional record update feature.
>>
>> Thanks
>>
>> Tom
>
>
> You can copy an object updating a value field, not a method field:
>
> class point (x:int) = object val x = x method get = x method bump dx = {< x = x+dx >} end
>
> You can use this for methods too, by having them call a function value field.
> However, this kind of update is only available inside methods, which requires some thinking
> when designing your code.
>
> I agree that what you suggest would be nice to have.
> There is no majore technical difficulty, but there would be some overhead.
>
> Jacques Garrigue
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-02 11:55 [Caml-list] Question about objects and method overriding Tom Ridge
2014-02-02 12:43 ` Jacques Garrigue
@ 2014-02-03 10:35 ` Goswin von Brederlow
2014-02-03 12:24 ` Tom Ridge
2014-02-03 13:55 ` Alain Frisch
2014-02-05 18:22 ` remy
2 siblings, 2 replies; 9+ messages in thread
From: Goswin von Brederlow @ 2014-02-03 10:35 UTC (permalink / raw)
To: caml-list
On Sun, Feb 02, 2014 at 11:55:02AM +0000, Tom Ridge wrote:
> Dear caml-list,
>
> With records, one can functionally update a field e.g. as
>
> { r with some_field=new_value }
>
> And new_value may, of course, be a function.
>
> With objects, is there similar functionality? e.g. can I write something like
>
> {{ myobj with method some_method=new_method }}
>
> ?
>
> Of course, I could copy the methods from myobj explicitly into a new
> object (and set some_method to new_method), but I might not know all
> the methods available on myobj, and even if I do this becomes
> textually extremely verbose.
>
> Of course, new_method cannot directly refer to self etc. Basically I
> am using objects in a similar way to records, and would like to use
> this functional record update feature.
>
> Thanks
>
> Tom
On the source level you can change a method by inheriting the old
class and implementing the method again. But you seem to want to
change the method at runtime. Problem there is that all instances of a
class afaik have the same virtual table to dispatch methods. So
changing a methong in one instance would change it in all.
But why not dispatch the method through a value of the insance using a
closure?
class myobj = object
val mutable call_fn = fun () -> ()
method call = call_fn ()
method set_call fn = call_fn <- fn
end
MfG
Goswin
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-03 10:35 ` Goswin von Brederlow
@ 2014-02-03 12:24 ` Tom Ridge
2014-02-03 15:54 ` Goswin von Brederlow
2014-02-03 13:55 ` Alain Frisch
1 sibling, 1 reply; 9+ messages in thread
From: Tom Ridge @ 2014-02-03 12:24 UTC (permalink / raw)
To: Goswin von Brederlow; +Cc: caml-list
The scenario might be: I don't have the ability to change the object
implementation to use an instance variable (perhaps the object comes
from a library I am using), or maybe I don't want to decide upfront
when I create the object, which methods can be overridden in this way
(i.e. I don't want to add explicit set_call methods for all functions
that I might want to override).
On 3 February 2014 10:35, Goswin von Brederlow <goswin-v-b@web.de> wrote:
> On Sun, Feb 02, 2014 at 11:55:02AM +0000, Tom Ridge wrote:
>> Dear caml-list,
>>
>> With records, one can functionally update a field e.g. as
>>
>> { r with some_field=new_value }
>>
>> And new_value may, of course, be a function.
>>
>> With objects, is there similar functionality? e.g. can I write something like
>>
>> {{ myobj with method some_method=new_method }}
>>
>> ?
>>
>> Of course, I could copy the methods from myobj explicitly into a new
>> object (and set some_method to new_method), but I might not know all
>> the methods available on myobj, and even if I do this becomes
>> textually extremely verbose.
>>
>> Of course, new_method cannot directly refer to self etc. Basically I
>> am using objects in a similar way to records, and would like to use
>> this functional record update feature.
>>
>> Thanks
>>
>> Tom
>
> On the source level you can change a method by inheriting the old
> class and implementing the method again. But you seem to want to
> change the method at runtime. Problem there is that all instances of a
> class afaik have the same virtual table to dispatch methods. So
> changing a methong in one instance would change it in all.
>
> But why not dispatch the method through a value of the insance using a
> closure?
>
> class myobj = object
> val mutable call_fn = fun () -> ()
> method call = call_fn ()
> method set_call fn = call_fn <- fn
> end
>
> MfG
> Goswin
>
> --
> Caml-list mailing list. Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-03 10:35 ` Goswin von Brederlow
2014-02-03 12:24 ` Tom Ridge
@ 2014-02-03 13:55 ` Alain Frisch
2014-02-03 15:12 ` Tom Ridge
1 sibling, 1 reply; 9+ messages in thread
From: Alain Frisch @ 2014-02-03 13:55 UTC (permalink / raw)
To: Goswin von Brederlow, caml-list
On 02/03/2014 11:35 AM, Goswin von Brederlow wrote:
> On the source level you can change a method by inheriting the old
> class and implementing the method again. But you seem to want to
> change the method at runtime. Problem there is that all instances of a
> class afaik have the same virtual table to dispatch methods. So
> changing a methong in one instance would change it in all.
Well, nothing prevent you from creating a fresh copy of the table for
the new object, as in:
let unsafe_override (o : 'a) (ov : < .. >) : 'a =
let o = Obj.repr (Oo.copy o) in
let meths = Obj.dup (Obj.field o 0) in
Obj.set_field o 0 meths;
let nmeths : int = Obj.magic (Obj.field meths 0) in
let ov = Obj.repr ov in
let new_meths = Obj.field ov 0 in
let nnew_meths : int = Obj.magic (Obj.field new_meths 0) in
let i = ref 0 and j = ref 0 in
while !i < nmeths && !j < nnew_meths do
let tag : int = Obj.magic (Obj.field meths (3 + 2 * !i)) in
let ntag : int = Obj.magic (Obj.field new_meths (3 + 2 * !j)) in
if tag < ntag then incr i
else if ntag < tag then incr j
else begin
let f : _ -> _ = Obj.magic (Obj.field new_meths (2 + 2 * !j)) in
Obj.set_field meths (2 + 2 * !i) (Obj.magic (fun _ -> f ov));
incr i;
incr j
end
done;
Obj.magic o
val unsafe_override : (< .. > as 'a) -> < .. > -> 'a = <fun>
This function returns a copy of its first argument (with the same type),
where the methods which are also defined in the second argument are
overridden with the implementation from the second argument (and when
they are called, their "self" is the second argument).
This is type-unsafe because one should enforce that methods common to
the two objects have the same type (and that there is no clash between
the hash value of their other methods). Is there a user-land hack to
encode this property (or a stronger one, such as the type of the first
argument be an extension of the type of the second argument)?
For a given list of methods, one can define safe (I believe!) instances
of unsafe_override, for instance:
let override_x_y : (< x : 'x; y : 'y; .. > as 'this) -> < x : 'x; y : 'y
> -> 'this = unsafe_override;;
This function can be used to override methods x and y of an object
having these methods and potentially more.
Some syntactic sugar could automate this a little bit. For instance,
with extension points, one could use a -ppx filter to rewrite:
[#oo_override x y]
into:
(unsafe_override : (< x : 'x; y : 'y; .. > as 'this) -> < x : 'x; y : 'y
> -> 'this)
(with same more unique names for the generated type variables)
Alain
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-03 13:55 ` Alain Frisch
@ 2014-02-03 15:12 ` Tom Ridge
0 siblings, 0 replies; 9+ messages in thread
From: Tom Ridge @ 2014-02-03 15:12 UTC (permalink / raw)
To: Alain Frisch; +Cc: Goswin von Brederlow, caml-list
>
> For a given list of methods, one can define safe (I believe!) instances of
> unsafe_override, for instance:
>
> let override_x_y : (< x : 'x; y : 'y; .. > as 'this) -> < x : 'x; y : 'y >
> -> 'this = unsafe_override;;
>
>
> This function can be used to override methods x and y of an object having
> these methods and potentially more.
>
I think this is exactly what I want! Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-03 12:24 ` Tom Ridge
@ 2014-02-03 15:54 ` Goswin von Brederlow
0 siblings, 0 replies; 9+ messages in thread
From: Goswin von Brederlow @ 2014-02-03 15:54 UTC (permalink / raw)
To: caml-list
On Mon, Feb 03, 2014 at 12:24:51PM +0000, Tom Ridge wrote:
> The scenario might be: I don't have the ability to change the object
> implementation to use an instance variable (perhaps the object comes
> from a library I am using), or maybe I don't want to decide upfront
> when I create the object, which methods can be overridden in this way
> (i.e. I don't want to add explicit set_call methods for all functions
> that I might want to override).
>
>
> On 3 February 2014 10:35, Goswin von Brederlow <goswin-v-b@web.de> wrote:
> > On Sun, Feb 02, 2014 at 11:55:02AM +0000, Tom Ridge wrote:
> >> Dear caml-list,
> >>
> >> With records, one can functionally update a field e.g. as
> >>
> >> { r with some_field=new_value }
> >>
> >> And new_value may, of course, be a function.
> >>
> >> With objects, is there similar functionality? e.g. can I write something like
> >>
> >> {{ myobj with method some_method=new_method }}
> >>
> >> ?
> >>
> >> Of course, I could copy the methods from myobj explicitly into a new
> >> object (and set some_method to new_method), but I might not know all
> >> the methods available on myobj, and even if I do this becomes
> >> textually extremely verbose.
> >>
> >> Of course, new_method cannot directly refer to self etc. Basically I
> >> am using objects in a similar way to records, and would like to use
> >> this functional record update feature.
> >>
> >> Thanks
> >>
> >> Tom
> >
> > On the source level you can change a method by inheriting the old
> > class and implementing the method again. But you seem to want to
> > change the method at runtime. Problem there is that all instances of a
> > class afaik have the same virtual table to dispatch methods. So
> > changing a methong in one instance would change it in all.
> >
> > But why not dispatch the method through a value of the insance using a
> > closure?
> >
> > class myobj = object
> > val mutable call_fn = fun () -> ()
> > method call = call_fn ()
> > method set_call fn = call_fn <- fn
> > end
> >
> > MfG
> > Goswin
class myobj = object
inherit libobj as parent
val mutable call_fn = fun () -> parent#call
method call = call_fn ()
method set_call fn = call_fn <- fn
end
You can always override the method of a given class.
But see other mail for the award deserving Obj.magic hack to change a
method on the fly.
MfG
Goswin
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] Question about objects and method overriding
2014-02-02 11:55 [Caml-list] Question about objects and method overriding Tom Ridge
2014-02-02 12:43 ` Jacques Garrigue
2014-02-03 10:35 ` Goswin von Brederlow
@ 2014-02-05 18:22 ` remy
2 siblings, 0 replies; 9+ messages in thread
From: remy @ 2014-02-05 18:22 UTC (permalink / raw)
To: caml-list
Tom,
I am afraid that what you would like to do is unsafe. Consider the following
example:
class a = object method a = 1 end
class ac = object (self : 'a) method a = 1 method c = 3 end
class ab = object method a = 1 method b = new a end
class abc = object (self : 'a)
method a = (self # b) # c
method b = self
method c = 2
end
let bug =
let abc = new abc in
let ab = (abc :> ab) in
let ab' : ab = (ab with b = new a)
ab' # a
This is typable in OCaml if you replace the penultimate line by let ab' = ab
According to your proposal, the penultimate line should typecheck as well
because we change method b of type a by a method of the same type.
However, the evaluation of bug creates a new object ab' with methods a, b,
and c but where b returns an object a' with a single method a. Therefore,
the evaluation of ab' # a will reduce to ab' # b # c then to a' # c which
will break.
----------------
The problem is that methods may receive self as argument, but this is not
traced in the object types---only in the class types.
If you replace method override by field override with a val call_b
and a method set_b as suggested, typechecking will break because
the type of self will then appear contra-variantly in method set_b which
will prevent subtyping (abc : ab).
In order to typecheck method overriding safely, one has to prevent the use
of subtyping altogether or track it field by field, but this quickly becomes
very tricky.
See for instance "From classes to objects via subtyping"
http://cristal.inria.fr/~remy/publications_abstracts.html#Remy/classes-to-objects/esop
Didier
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-02-05 18:22 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-02 11:55 [Caml-list] Question about objects and method overriding Tom Ridge
2014-02-02 12:43 ` Jacques Garrigue
2014-02-02 12:50 ` Tom Ridge
2014-02-03 10:35 ` Goswin von Brederlow
2014-02-03 12:24 ` Tom Ridge
2014-02-03 15:54 ` Goswin von Brederlow
2014-02-03 13:55 ` Alain Frisch
2014-02-03 15:12 ` Tom Ridge
2014-02-05 18:22 ` remy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox