(**************************************************************************)
(*                                                                        *)
(*                                 OCaml                                  *)
(*                                                                        *)
(*             Damien Doligez, projet Para, INRIA Rocquencourt            *)
(*                                                                        *)
(*   Copyright 1997 Institut National de Recherche en Informatique et     *)
(*     en Automatique.                                                    *)
(*                                                                        *)
(*   All rights reserved.  This file is distributed under the terms of    *)
(*   the GNU Lesser General Public License version 2.1, with the          *)
(*   special exception on linking described in the file LICENSE.          *)
(*                                                                        *)
(**************************************************************************)

(** Deferred computations. *)

type 'a t = 'a CamlinternalLazy.t
(** A value of type ['a Lazy.t] is a deferred computation, called a suspension,
    that has a result of type ['a]. The special expression syntax [lazy (expr)]
    makes a suspension of the computation of [expr], without computing
    [expr] itself yet. "Forcing" the suspension will then compute [expr] and
    return its result. Matching a suspension with the special pattern syntax
    [lazy(pattern)] also computes the underlying expression and tries to bind
    it to [pattern]:

    {[
      let lazy_option_map f x =
      match x with
      | lazy (Some x) -> Some (Lazy.force f x)
      | _ -> None
    ]}

    Note: If lazy patterns appear in multiple cases in a pattern-matching, lazy
    expressions may be forced even outside of the case ultimately selected by
    the pattern matching. In the example above, the suspension [x] is always
    computed.

    Note: [lazy_t] is the built-in type constructor used by the compiler for the
    [lazy] keyword.  You should not use it directly.  Always use [Lazy.t]
    instead.

    Note: [Lazy.force] is not concurrency-safe. If you use this module with
    multiple fibers, systhreads or domains, then you will need to add some
    locks. The module however ensures memory-safety, and hence, concurrently
    accessing this module will not lead to a crash but the behaviour is
    unspecified.

    Note: if the program is compiled with the [-rectypes] option,
    ill-founded recursive definitions of the form [let rec x = lazy x]
    or [let rec x = lazy(lazy(...(lazy x)))] are accepted by the type-checker
    and lead, when forced, to ill-formed values that trigger infinite
    loops in the garbage collector and other parts of the run-time system.
    Without the [-rectypes] option, such ill-founded recursive definitions
    are rejected by the type-checker.
*)


exception Undefined
(** Raised when forcing a suspension concurrently from multiple fibers,
    systhreads or domains, or when the suspension tries to force itself
    recursively.
*)

external force : 'a t -> 'a = "%lazy_force"
(** [force x] forces the suspension [x] and returns its result. If [x] has
    already been forced, [Lazy.force x] returns the same value again without
    recomputing it.  If it raised an exception, the same exception is raised
    again.

    @raise Undefined (see {!Undefined}).
*)

(** {1 Iterators} *)

val map : ('a -> 'b) -> 'a t -> 'b t
(** [map f x] returns a suspension that, when forced,
    forces [x] and applies [f] to its value.

    It is equivalent to [lazy (f (Lazy.force x))].

    @since 4.13
*)

(** {1 Reasoning on already-forced suspensions} *)

val is_val : 'a t -> bool
(** [is_val x] returns [true] if [x] has already been forced and
    did not raise an exception.
    @since 4.00 *)

val from_val : 'a -> 'a t
(** [from_val v] evaluates [v] first (as any function would) and returns
    an already-forced suspension of its result.
    It is the same as [let x = v in lazy x], but uses dynamic tests
    to optimize suspension creation in some cases.
    @since 4.00 *)

val map_val : ('a -> 'b) -> 'a t -> 'b t
(** [map_val f x] applies [f] directly if [x] is already forced,
   otherwise it behaves as [map f x].

   When [x] is already forced, this behavior saves the construction of
   a suspension, but on the other hand it performs more work eagerly
   that may not be useful if you never force the function result.

   If [f] raises an exception, it will be raised immediately when
   [is_val x], or raised only when forcing the thunk otherwise.

   If [map_val f x] does not raise an exception, then
   [is_val (map_val f x)] is equal to [is_val x].

    @since 4.13 *)


(** {1 Advanced}

   The following definitions are for advanced uses only; they require
   familiarity with the lazy compilation scheme to be used appropriately. *)

val from_fun : (unit -> 'a) -> 'a t
(** [from_fun f] is the same as [lazy (f ())] but slightly more efficient.

    It should only be used if the function [f] is already defined.
    In particular it is always less efficient to write
    [from_fun (fun () -> expr)] than [lazy expr].

    @since 4.00 *)

val force_val : 'a t -> 'a
(** [force_val x] forces the suspension [x] and returns its result.  If [x]
    has already been forced, [force_val x] returns the same value again
    without recomputing it.

    If the computation of [x] raises an exception, it is unspecified
    whether [force_val x] raises the same exception or {!Undefined}.
    @raise Undefined if the forcing of [x] tries to force [x] itself
    recursively.

    @raise Undefined (see {!Undefined}).
*)
