From: philippe <kelvin.bitnick@gmail.com>
To: caml-list@yquem.inria.fr
Subject: Re: objects: the lack of method overloading (looking for a way around it)
Date: Tue, 5 Oct 2010 17:37:07 +0200 [thread overview]
Message-ID: <AANLkTimaC9GAyAMX0PVk6-E6cQ8bbZWJQfZ48qKAd+U=@mail.gmail.com> (raw)
In-Reply-To: <AANLkTimt5Uvd0t=YrHbXwy=1Atk1+1QLKViSwMkwNoCk@mail.gmail.com>
philippe,
use parametrized classes.
--
philippe
On Mon, Oct 4, 2010 at 7:32 PM, philippe <kelvin.bitnick@gmail.com> wrote:
> Hello,
>
> I'm just beginning a real, usefull usage of the object system in ocaml.
> I'm a bit stalled on one thing, it's the lack of method overloading like in C++.
> My need is in a case of building a rather simple pipeline pattern:
> each instance of an element (a node) in the pipeline can get a
> numerical value from the previous node, do some computation on it, and
> store it locally in a hash for caching/efficiency, as returning it
> using the #get method.
>
> The real need see most of the time a 1D array of float (a vector) in
> input and output of each node.
> but sometime a Complex.t array.
>
> So I need some kind of polymorphism for allowing :
>
> float array -> float array
> Complet.t array -> float array
> float array -> Complex.t array
> Complex.t array -> Complex.t array
>
> Here's a shorter (a bit dumb) demo code using int -> int.
>
> (I would much prefer avoid to store float in the real part of a
> complex array - in the real (genuine) code the array may be long,
> 100'000 elements and more, it's code a bit sensitive about
> performances).
>
> Look to the comment MY QUESTION in the definition of the process
> method in the class node_plus
>
> THANK YOU !
>
> --
> Philippe Strauss
>
> --- 8< ---
>
> open Common
> open Log
>
> (* the real code has more usefull type here *)
> type node_parameters = Plus1 | Plus2
>
> (* a class for storing parameters usefull for the whole pipeline chain *)
> class parameters =
> object(self)
> (* useless here - usefull in the real code *)
> val mutable sf = 44100
> (* a value we will add in a demo node *)
> val mutable add = 1
> method get_sf = sf
> method set_sf sfreq =
> sf <- sfreq ;
> method get_add = add
> method set_add ntoadd =
> add <- ntoadd
> (* this is for the cache part of each node: we compute a hash
> of parameter to distinguish hash entries btwn parameters change *)
> method get_parh np (node_id: int) =
> let md5 s = Digest.to_hex (Digest.string s) in
> match np with
> (* the real code doesn't use always (sf, add) but
> parameter influing the processing of a node *)
> | Plus1 -> md5 (Marshal.to_string (sf, add) [Marshal.No_sharing])
> | Plus2 -> md5 (Marshal.to_string (sf, add) [Marshal.No_sharing])
> end
>
> (* main code of a node: a boileplate around a hash to cache computed value *)
> class virtual node_virt prev parm hn =
> object(self)
> (* instance of a previous node in the pipeline *)
> val previous = prev
> (* instance of the parameters *)
> val parms = parm
> (* the hash for caching *)
> val hres = Hashtbl.create hn
> (* a serial, bumped up plus one on each cache miss *)
> val mutable id = 0
> method get_id = id
> method inc_id =
> id <- id + 1
> (* for passing to (parms #get_parh (self #ptyp ())) in the
> real code, when adding a result into the hash *)
> method virtual ptyp: unit -> node_parameters
> (* the real computation is defined in a non virtual method
> later, as simply as possible *)
> method virtual process: int -> int
> (* process and store: call process, then store in cache.
> called on a cache miss *)
> method private pstore: (int * int) =
> let prid, data = prev #get in
> (* processing *)
> let new_data = self #process data in
> (* we're in a cache miss: bump the serial +1 *)
> self #inc_id ;
> let myid = self #get_id in
> Hashtbl.add hres (parms #get_parh Plus1 myid) new_data ;
> (myid, new_data)
> method get =
> try
> (* memoize id to avoid race cond *)
> let myid = self #get_id in
> (* here again in the real code, we lookup the hash
> using (parms #get_parh (self #ptyp ()) myid) *)
> let data = Hashtbl.find hres (parms #get_parh Plus1 myid) in
> (myid, data)
> with Not_found -> Printf.printf "node_virt #get: cache
> miss!\n%!"; self #pstore
> end
>
> (* a trivial node: add parm #get_add to the integer we receive from
> the previous node *)
> class node_plus prev parm hn =
> object(self)
> inherit node_virt prev parm hn
> method ptyp () = Plus1
> (*
> MY QUESTION: what is the best way to allow not only int ->
> int for this process method,
> but also: int -> float, float -> int, float -> float ?
> The method minimizing the code written in this non virtual
> node definition, since I may end with 15 or 30
> differents derived class of node_virt like this single one ?
> *)
> method process n =
> n + (parm #get_add)
> end
>
> (* a front of line, head node having a get method of the same type
> than those derived from node_virt *)
> class node_head parm =
> object(self)
> val parms = parm
> method get =
> (0, 1)
> end
>
>
> let () =
> let p = new parameters in
> p #set_sf 44100 ; (* useless indeed, just for demo *)
> p #set_add 2 ; (* usefull *)
> let n0 = new node_head p in
> let n1 = new node_plus n0 p 3 in
> Printf.printf "%d\n" (snd (n0 #get)) ;
> Printf.printf "%d\n" (snd (n1 #get)) ;
> Printf.printf "%d\n" (snd (n1 #get)) ;
> p #set_add 1 ;
> Printf.printf "%d\n" (snd (n1 #get))
>
prev parent reply other threads:[~2010-10-05 15:37 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-04 17:32 philippe
2010-10-05 15:37 ` philippe [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='AANLkTimaC9GAyAMX0PVk6-E6cQ8bbZWJQfZ48qKAd+U=@mail.gmail.com' \
--to=kelvin.bitnick@gmail.com \
--cc=caml-list@yquem.inria.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox