caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Xavier Leroy <xleroy@pomerol>
To: caml-list@margaux
Cc: rbrena@mtecv2.mty.itesm.mx
Subject: Lazy evaluation in Caml Light
Date: Tue, 6 Oct 92 13:26:22 MET	[thread overview]
Message-ID: <9210061226.AA16903@pomerol.inria.fr> (raw)

I've been asked questions about lazy evaluation in Caml Light several
times already, so I'd like to summarize.

- It is straightforward to implement delayed expressions, as with the
"delay" function in Scheme, using mutable data structures. I have
enclosed a sample implementation below. This solution is certainly not
elegant --- the user's code is cluttered by explicit "freeze" and
"unfreeze" operations --- but at least you can really understand
what's going on.

- As pointed out by Michel Mauny, streams do not provide a general
lazy evaluation mechanism: granted, they are lazily evaluated, but the
"discard after use" semantics for stream matching is generally not
what you want to implement e.g. potentially infinite data structures.

- I'm reluctant to integrate lazy evaluation in the Caml Light system,
not only because I'd like Caml Light to remain small and simple, but
also because there is no obvious, universally accepted way to
integrate lazy evaluation within a strict language. Also,
understanding the interaction between lazy evaluation and side-effects
is quite hard; the best way I know is to think in terms of the
underlying implementation in terms of mutable structures --- just as
in the first point above.

- Xavier Leroy

(* The poor man's lazy evaluation in CAML Light *)

(* Interface file: lazy.mli *)

type 'a suspension;;

value freeze : (unit -> 'a) -> 'a suspension
  and unfreeze : 'a suspension -> 'a;;

(* Implementation file: lazy.ml *)

type 'a suspension =
  { mutable state: 'a suspension_state }
and 'a suspension_state =
    Unevaluated of (unit -> 'a)
  | Evaluated of 'a
;;

let freeze expr =
  { state = Unevaluated expr }
;;

let unfreeze susp =
  match susp.state with
    Unevaluated f ->
      let val = f () in
        susp.state <- Evaluated val; val
  | Evaluated val ->
      val
;;

(* An example: lazy streams *)

type 'a stream =
  { head : 'a;
    tail : 'a stream suspension }
;;

(* Getting the Nth element of a stream *)

let rec nth_stream stream n =
  if n <= 0 then stream.head else nth_stream (unfreeze stream.tail) (n-1)
;;

(* Mapping on a stream *)

let rec map_stream f stream =
  { head = f stream.head;
    tail = freeze(fun () -> map_stream f (unfreeze stream.tail)) }
;;

(* The stream of all positive integers *)

let rec positive_integers =
  { head = 0;
    tail = freeze(fun () -> map_stream (fun x -> x+1) positive_integers) }
;;

nth_stream positive_integers 10;;
positive_integers;;





                 reply	other threads:[~1992-10-06 12:52 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=9210061226.AA16903@pomerol.inria.fr \
    --to=xleroy@pomerol \
    --cc=caml-list@margaux \
    --cc=rbrena@mtecv2.mty.itesm.mx \
    /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).