caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* 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

* Re: [Caml-list] OCaml object types vs record types
  2007-06-04 20:13 ` Nicolas Pouillard
@ 2007-06-04 22:06   ` Lukasz Stafiniak
  0 siblings, 0 replies; 4+ messages in thread
From: Lukasz Stafiniak @ 2007-06-04 22:06 UTC (permalink / raw)
  To: caml-list

On 6/4/07, Nicolas Pouillard <nicolas.pouillard@gmail.com> wrote:
>
> 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)
>
It seems to make for "polymorphic records", for which I've asked some time ago.
(The lightest thing that allows for record label reuse by structural subtyping.)


^ 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;
as well as URLs for NNTP newsgroup(s).