caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Max Kirillov <max630@mail.ru>
To: caml-list@inria.fr
Subject: Re: [Caml-list] static variables in a function
Date: Sun, 16 Jun 2002 02:19:02 +0700	[thread overview]
Message-ID: <20020616021902.A22564@max.home> (raw)
In-Reply-To: <86y9dgo6y6.fsf@laurelin.dementia.org>; from j.prevost@cs.cmu.edu on Sat, Jun 15, 2002 at 12:14:09PM -0400

[-- Attachment #1: Type: text/plain, Size: 2419 bytes --]

On Sat, Jun 15, 2002 at 12:14:09PM -0400, John Prevost wrote:
<...>
> If we change our focus, howeverm the technique becomes more
> interesting.  Take a look at this, for example:
<...>
> let memoize f =

Hmm... this isn't executed at read time because function has
a parameter...

>   let stow = Hashtbl.create 20 in
>   fun x -> begin
>     if not (Hashtbl.mem stow x) then begin
>       try (let v = f x in Hashtbl.replace stow x (Val v))
>         with e -> Hashtbl.replace stow x (Exn e)
>      end;
>     match Hashtbl.find stow x with
>       | Val x -> x
>       | Exn e -> raise e
>   end
<...>
> let rec fib_r2 x =
>   memoize (fib' fib_r2) x

The function memoize (and even "memoize (fib' fib_r2)" with
a variable first parameter) as called at every recursion
step and therefore no caching will be performed. (I've
tested it).

The working way is:

let fib_r3 = memoize fib_r1

which is, btw, very similar to

let fib_r3 = new memoize fib_r1

> In this case, the whole point of the function is that it produces a
> function identical in every way to the original function, except that
> it memoizes its work so as not to repeat.  There's no convenient
> "object" to stuff the value into, because the function *is* our
> object.  The only way we can store the data correctly is to have the
> information somehow attached to the function we're creating.

Well, OO-biased programmer would say it's a good reson to
_make_ an object with only one exported method. Nearly any
programmer would say that we should make an object to
provide additional control, say, to clear the cache.

I've played with it a bit, and discover that there are many
ways to do the job. Three files attached contains three ways
of doing the same things via function returned from
initialization func (accPart.ml), commonly known OO-patterns
(accClass.ml) and modules system (accMod.ml). Tha task is to
remember a function and initial value, then sending operands
for successive applications of function.

To allow several "methods" to deal with data object we must
return several function, not just one. Moreover, we cannot
use inheritance, as we can with classes.

accMod.ml discovers generally the same features as
accClass.ml, but contains a bit more verbose writing. Maybe,
modules is not a good way to contain persistent mutable
value.

Max.

PS: maybe in version2 one could use record with labelled
things, to make it a bit nicer.

[-- Attachment #2: accPart.ml --]
[-- Type: text/plain, Size: 641 bytes --]

let p s n = print_string (s^string_of_int n^"\n"); flush stdout

(*version 1*)
let acc f init =
    let vR = ref init in
    let fApp x =
	let newX = f !vR x in
	vR := newX;
	newX in
    fApp

let f1 = acc (+) 0

let _ = p "f1:" (f1 1)
let _ = p "f1:" (f1 1)
let _ = p "f1:" (f1 1)

(*version 2*)
let acc' f init =
    let vR = ref init in
    let fApp x =
	let newX = f !vR x in
	vR := newX;
	newX
    and fIni x = (vR := x) in
    (fApp,fIni)

let (f1a,f1i) = acc' (+) 0

let _ = p "f1a:" (f1a 1)
let _ = p "f1a:" (f1a 1)
let _ = p "f1a:" (f1a 1)
let _ = f1i (-5)
let _ = p "f1a:" (f1a 1)
let _ = p "f1a:" (f1a 1)
let _ = p "f1a:" (f1a 1)

[-- Attachment #3: accClass.ml --]
[-- Type: text/plain, Size: 667 bytes --]

let p s n = print_string (s^string_of_int n^"\n"); flush stdout

(*version 1*)
class ['a,'b] acc f init = object
    val mutable v = (init:'a)
    val func = (f:'a -> 'b -> 'a)
    method app x =
	let newX = func v x in
	v <- newX;newX
end

let f1 = new acc (+) 0

let _ = p "f1:" (f1#app 1)
let _ = p "f1:" (f1#app 1)
let _ = p "f1:" (f1#app 1)

(*version 2*)
class ['a,'b] acc' f init = object
    inherit ['a,'b] acc f init
    method init x = v <- x
end

let f2 = new acc' (+) 0

let _ = p "f2:" (f2#app 1)
let _ = p "f2:" (f2#app 1)
let _ = p "f2:" (f2#app 1)
let _ = f2#init (-5)
let _ = p "f2:" (f2#app 1)
let _ = p "f2:" (f2#app 1)
let _ = p "f2:" (f2#app 1)

[-- Attachment #4: accMod.ml --]
[-- Type: text/plain, Size: 951 bytes --]

let p s n = print_string (s^string_of_int n^"\n"); flush stdout

module type AccArgT = sig
    type t and t1
    val init: t
    val f: t -> t1 -> t
end

module AccArgInt(I:sig val init:int val f:int->int->int end) = struct
    type t = int and t1 = int
    let init = I.init and f = I.f
end

(*version 1*)
module Acc(T:AccArgT) = struct
    let vR = ref T.init
    let func = T.f
    let app x =
	let newX = func !vR x in
	vR := newX;newX
end

module F1 = Acc(AccArgInt(struct let init = 0 and f = (+) end))

let _ = p "f1:" (F1.app 1)
let _ = p "f1:" (F1.app 1)
let _ = p "f1:" (F1.app 1)

(*version 2*)
module Acc1(T:AccArgT) = struct
    module A = Acc(T)
    include A
    let init x = vR:=x
end

module F2 = Acc1(AccArgInt(struct let init = 0 and f = (+) end))

let _ = p "f2:" (F2.app 1)
let _ = p "f2:" (F2.app 1)
let _ = p "f2:" (F2.app 1)
let _ = F2.init (-5)
let _ = p "f2:" (F2.app 1)
let _ = p "f2:" (F2.app 1)
let _ = p "f2:" (F2.app 1)

  reply	other threads:[~2002-06-15 19:21 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-06-14 17:08 Shannon --jj Behrens
2002-06-14 17:40 ` Stefano Zacchiroli
2002-06-14 17:58 ` Yutaka OIWA
2002-06-14 20:43   ` Shannon --jj Behrens
2002-06-15  4:42   ` Max Kirillov
2002-06-15  6:36     ` John Prevost
2002-06-15 14:51       ` Max Kirillov
2002-06-15 16:14         ` John Prevost
2002-06-15 19:19           ` Max Kirillov [this message]
2002-06-15 23:16             ` John Prevost
2002-06-16 23:19             ` Remi VANICAT
2002-06-17 13:56               ` [Caml-list] Memoizing (was: static variables...) Benedikt Rosenau
2002-06-18  8:40                 ` William Lovas
2002-06-18  9:16                   ` Jacek Chrzaszcz
2002-06-18 21:52                     ` William Lovas
2002-06-18 13:07                   ` Christopher Quinn
2002-06-18 14:07                     ` Remi VANICAT
2002-06-18 17:52                       ` Christopher Quinn
2002-06-19 14:42                   ` John Max Skaller
2002-06-23 21:18                     ` Pierre Weis
2002-06-19  4:38   ` [Caml-list] static variables in a function Shannon --jj Behrens

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=20020616021902.A22564@max.home \
    --to=max630@mail.ru \
    --cc=caml-list@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;
as well as URLs for NNTP newsgroup(s).