(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
Ltac2 Type 'a lazy_data := [ Value ('a) | Thunk (unit -> 'a) ].
(** Type of a lazy cell, similar to OCaml's ['a Lazy.t] type. The functions of thismoduledonothaveanyspecificbacktrackingsupport,soanyfunction passedtoprimitivesofthismoduleishandledasifithadonesuccessat
most (potential other successes are ignored). *)
Ltac2 Type 'a t := 'a lazy_data Ref.ref.
(** [from_val v] creates a new lazy cell storing (already-computed) value [v]. Forcing(i.e.,usingthe[force]functionon)theproducedcellgivesback
value [v], and never gives an exception. *)
Ltac2 from_val (v : 'a) : 'a t :=
Ref.ref (Value v).
(** [from_fun f] creates a new lazy cell from the given thunk [f]. There is no specificsupportforbacktrackinginthe[Lazy]module,soif[f]hasmore
than one success, only the first one will be considered. *)
Ltac2 from_fun (f : unit -> 'a) : 'a t :=
Ref.ref (Thunk f).
(** [is_val r] indicates whether the given lazy cell [r] holds a forced value. Inparticular,[is_valr]alwaysreturns[true]if[r]wascreatedviathe [from_val]function.If[r]wascreatedusing[from_fun],then[true]will onlybereturnedifthevalueof[r]waspreviouslyforced(e.g.,withthe
[force] function), and if no exception was produced by said forcing. *)
Ltac2 is_val (r : 'a t) : bool := match Ref.get r with
| Value _ => true
| Thunk _ => false end.
(** Exception raised in case of a "cyclic" lazy cell. *)
Ltac2 Type exn ::= [ Undefined ].
(** [force r] gives the value represented by the lazy cell [r], which requires forcingathunkandupdating[r]totheproducedvalueif[r]doesnotyet haveavalue.Notethatifforcingproducesanexception,subsequentcalls to[force]willimmediatelyyieldthesameexception(withoutre-computing thewholethunk).Additionally,the[Undefined]exceptionisproduced(and settobeproducedby[r]onsubsequentcallsto[force])if[r]relieson
its own value for its definition (i.e., if [r] is "cyclic"). *)
Ltac2 force (r : 'a t) : 'a := match Ref.get r with
| Value v => v
| Thunk f =>
Ref.set r (Thunk (fun () => Control.throw Undefined)); match Control.case f with
| Val (v, _) =>
Ref.set r (Value v);
v
| Err e =>
Ref.set r (Thunk (fun () => Control.zero e));
Control.zero e end end.
(** [map f r] is equivalent to [from_fun (fun () => f (force r))]. *)
Ltac2 map (f : 'a -> 'b) (r : 'a t) : 'b t :=
from_fun (fun () => f (force r)).
(** [map_val f r] is similar to [map f r], but the function [f] is immediately appliedif[r]containsaforcedvalue.Iftheimmediateapplicationgives anexception,thenanysubsequentforcingofproducedlazycellwillraise
the same exception. *)
Ltac2 map_val (f : 'a -> 'b) (r : 'a t) : 'b t := match Ref.get r with
| Value v => match Control.case (fun () => f v) with
| Val (v, _) => from_val v
| Err e => from_fun (fun () => Control.zero e) end
| Thunk t => from_fun (fun () => f (t ())) end.
ModuleExport Notations.
Ltac2 Notation"lazy!" f(thunk(self)) := from_fun f. End Notations.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.