* OCaml object types vs record types
@ 2007-06-04 16:45 Raj B
2007-06-04 19:55 ` [Caml-list] " Pierre-Evariste Dagand
2007-06-04 20:13 ` Nicolas Pouillard
0 siblings, 2 replies; 4+ messages in thread
From: Raj B @ 2007-06-04 16:45 UTC (permalink / raw)
To: caml-list
Hi there
I'm writing an application where I'd modeling objects as record
types. However, I'd like to have a subtyping relation between them
along with (occasional) coercion. For example,
type obj = {name : string}
type specialobj = {name: string; mutable value: int;...}
and so on...
Obviously, records obviously don't allow me to do this. In fact, I
can't even define two record types with the same field 'name'. I have
to define the 'largest' possible type i.e. specialobj and just leave
fields undefined (default value) when I don't need them. This is
fine, except that it eats up tons of memory because my records are
quite large and slows things down. On profiling, I find that most of
my time goes in the OCaml function 'caml_dup', which, I believe,
copies structures. I am very concerned about speed in my application.
I'm not sure I need the entire machinery of classes (since, I
understand that it can be pretty slow too?) and all that goes with
it, so I was wondering if using object types might serve the purpose.
type obj = <name : string>
type specialobj = <name: string; mutable value: int;...>
Unfortunately, it doesn't seem possible to define 'mutable' fields in
the same way as records. I'd have to define methods to get and set
values, so it seems like there's very little difference from class
definitions. Please correct me if I'm wrong.
Is there any way to get what I want (records with subtyping/coercion
behavior) without using classes? In case I do end up using classes,
what kind of performance penalty am I looking at?
Thanks!
Raj
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Caml-list] OCaml object types vs record types
2007-06-04 16:45 OCaml object types vs record types Raj B
@ 2007-06-04 19:55 ` Pierre-Evariste Dagand
2007-06-04 20:13 ` Nicolas Pouillard
1 sibling, 0 replies; 4+ messages in thread
From: Pierre-Evariste Dagand @ 2007-06-04 19:55 UTC (permalink / raw)
To: caml-list
You might be able to modelize objects with record through functors.
Let's give a try. Firstly, encapsulate the record and its methods in a
module Obj :
module type OBJ =
sig
type obj
val new_obj : string -> obj
val get_name : obj -> string
end
;;
module FObj =
struct
type obj = { name : string }
let new_obj s = { name = s }
let get_name obj = obj.name
end
;;
module Obj = (FObj : OBJ)
;;
There we have a basic object, additional methods operating on Obj.obj,
especially to_string, could be useful and implemented in the module.
Now, define the special object over Obj :
module FSpecialObjInt (Obj : OBJ) =
struct
type obj = { mutable value : int ; extends : Obj.obj }
let new_obj name value = { value = value ; extends = Obj.new_obj name }
let get_name obj = Obj.get_name obj.extends
let get_value obj = obj.value
let set_value obj v = obj.value <- v
end
module type SPECIAL_OBJ_INT =
sig
type obj
val new_obj : string -> int -> obj
val get_name : obj -> string
val get_value : obj -> int
val set_value : obj -> int -> unit
end
module SpecialObjInt = FSpecialObjInt(Obj)
Thus we have extended Obj by adding a value record plus its
getter/setter. Again, methods on SpecialObjInt could be put in the
functor.
We could also build a special object on Float :
module FSpecialObjFloat (Obj : OBJ) =
struct
type obj = { mutable value : float ; extends : Obj.obj }
let new_obj name value = { value = value ; extends = Obj.new_obj name }
let get_name obj = Obj.get_name obj.extends
let get_value obj = obj.value
let set_value obj v = obj.value <- v
end
module type SPECIAL_OBJ_FLOAT =
sig
type obj
val new_obj : string -> float -> obj
val get_name : obj -> string
val get_value : obj -> float
val set_value : obj -> float -> unit
end
module SpecialObjFloat = FSpecialObjFloat(Obj)
Again, we have extended Obj.
But the most interesting might be to build a super object of
SpecialObjInt and SpecialObjFloat :
module FSuperObj (ObjInt : SPECIAL_OBJ_INT) (ObjFloat : SPECIAL_OBJ_FLOAT) =
struct
type obj = { name : string ;
extends_int : ObjInt.obj ;
extends_float : ObjFloat.obj }
let new_obj super_name int_name int_value float_name float_value =
{
name = super_name ;
extends_int = ObjInt.new_obj int_name int_value ;
extends_float = ObjFloat.new_obj float_name float_value
}
let get_int_name obj = ObjInt.get_name obj.extends_int
let get_int_value obj = ObjInt.get_value obj.extends_int
let set_int_value obj v = ObjInt.set_value obj.extends_int v
let get_float_name obj = ObjFloat.get_name obj.extends_float
let get_float_value obj = ObjFloat.get_value obj.extends_float
let set_float_value obj v = ObjFloat.set_value obj.extends_float v
let get_name obj = obj.name
let to_string obj =
let name = get_name obj
and int_name = get_int_name obj
and int_value = get_int_value obj
and float_name = get_float_name obj
and float_value = get_float_value obj
in
"Name : " ^ name ^ "\n\t" ^
"Int name : " ^ int_name ^ "\n\t" ^
"Int value : " ^ (string_of_int int_value) ^ "\n\t" ^
"Float name : " ^ float_name ^ "\n\t" ^
"Float value : " ^ (string_of_float float_value) ^ "\n"
end
module type SUPER_OBJ =
sig
type obj
val new_obj : string -> string -> int -> string -> float -> obj
val get_int_name : obj -> string
val get_int_value : obj -> int
val set_int_value : obj -> int -> unit
val get_float_name : obj -> string
val get_float_value : obj -> float
val set_float_value : obj -> float -> unit
val get_name : obj -> string
val to_string : obj -> string
end
module SuperObj = FSuperObj(SpecialObjInt)(SpecialObjFloat)
Let's use it :
(* Basic obj *)
let obj = Obj.new_obj "test";;
Obj.get_name obj;;
(* First special obj *)
let special_obj1 = SpecialObjInt.new_obj "test" 2
;;
let name = SpecialObjInt.get_name special_obj1
and value = SpecialObjInt.get_value special_obj1;;
SpecialObjInt.set_value special_obj1 3;;
let value = SpecialObjInt.get_value special_obj1;;
(* The same for the second special obj *)
(* Super obj *)
let super_obj = SuperObj.new_obj "Super Obj" "Int obj" 2 "Float obj" 4.2
;;
let name = SuperObj.get_name super_obj
and int_name = SuperObj.get_int_name super_obj
and int_value = SuperObj.get_int_value super_obj
and float_name = SuperObj.get_float_name super_obj
and float_value = SuperObj.get_float_value super_obj
;;
print_string (SuperObj.to_string super_obj);;
SuperObj.set_int_value super_obj 1;;
SuperObj.set_float_value super_obj 1.2;;
print_string (SuperObj.to_string super_obj);;
The main point with using functors is performance : while using
functors in a project of mine, I have noticed about 12% performance
lost compared to a raw implementation. Besides, in the present code,
there could be a deep cascade of function calls so you might not
achieve good performance. To my mind, defunctorisation would be really
usefull in that case.
2007/6/4, Raj B <rajb@rice.edu>:
> Hi there
>
> I'm writing an application where I'd modeling objects as record
> types. However, I'd like to have a subtyping relation between them
> along with (occasional) coercion. For example,
>
> type obj = {name : string}
> type specialobj = {name: string; mutable value: int;...}
> and so on...
>
> Obviously, records obviously don't allow me to do this. In fact, I
> can't even define two record types with the same field 'name'. I have
> to define the 'largest' possible type i.e. specialobj and just leave
> fields undefined (default value) when I don't need them. This is
> fine, except that it eats up tons of memory because my records are
> quite large and slows things down. On profiling, I find that most of
> my time goes in the OCaml function 'caml_dup', which, I believe,
> copies structures. I am very concerned about speed in my application.
>
> I'm not sure I need the entire machinery of classes (since, I
> understand that it can be pretty slow too?) and all that goes with
> it, so I was wondering if using object types might serve the purpose.
>
> type obj = <name : string>
> type specialobj = <name: string; mutable value: int;...>
>
> Unfortunately, it doesn't seem possible to define 'mutable' fields in
> the same way as records. I'd have to define methods to get and set
> values, so it seems like there's very little difference from class
> definitions. Please correct me if I'm wrong.
>
> Is there any way to get what I want (records with subtyping/coercion
> behavior) without using classes? In case I do end up using classes,
> what kind of performance penalty am I looking at?
>
> Thanks!
> Raj
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
--
Pierre-Evariste DAGAND
http://perso.eleves.bretagne.ens-cachan.fr/~dagand/
Empreinte GPG [pgp.mit.edu] :
F8CC 61DD 40B7 933F 17CA 061F 5591 AAE6 D3EC 7357
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Caml-list] OCaml object types vs record types
2007-06-04 16:45 OCaml object types vs record types Raj B
2007-06-04 19:55 ` [Caml-list] " Pierre-Evariste Dagand
@ 2007-06-04 20:13 ` Nicolas Pouillard
2007-06-04 22:06 ` Lukasz Stafiniak
1 sibling, 1 reply; 4+ messages in thread
From: Nicolas Pouillard @ 2007-06-04 20:13 UTC (permalink / raw)
To: Raj B; +Cc: caml-list
On 6/4/07, Raj B <rajb@rice.edu> wrote:
> Hi there
>
> I'm writing an application where I'd modeling objects as record
> types. However, I'd like to have a subtyping relation between them
> along with (occasional) coercion. For example,
>
> type obj = {name : string}
> type specialobj = {name: string; mutable value: int;...}
> and so on...
>
The pa_oo extension from Jacques Garrigue does exactly this kind of things:
http://www.math.nagoya-u.ac.jp/~garrigue/code/ocaml.html
(works also in 3.10 but not released yet, contact me if you want it)
Example:
type obj = <name : string>
type specialobj = <name: string; value: int; set_value: int -> unit...>
let o = {| name = "foo"; mutable value = 42 |}
in o#name, o#value <- 43, o#value
Regards,
--
Nicolas Pouillard
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-06-04 22:06 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-04 16:45 OCaml object types vs record types Raj B
2007-06-04 19:55 ` [Caml-list] " Pierre-Evariste Dagand
2007-06-04 20:13 ` Nicolas Pouillard
2007-06-04 22:06 ` Lukasz Stafiniak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox