1
0
Fork 0
cl-sites/guile.html_node/Fluids-and-Dynamic-States.html
2024-12-17 12:49:28 +01:00

286 lines
23 KiB
HTML

<!DOCTYPE html>
<html>
<!-- Created by GNU Texinfo 7.1, https://www.gnu.org/software/texinfo/ -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- This manual documents Guile version 3.0.10.
Copyright (C) 1996-1997, 2000-2005, 2009-2023 Free Software Foundation,
Inc.
Copyright (C) 2021 Maxime Devos
Copyright (C) 2024 Tomas Volf
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled "GNU Free
Documentation License." -->
<title>Fluids and Dynamic States (Guile Reference Manual)</title>
<meta name="description" content="Fluids and Dynamic States (Guile Reference Manual)">
<meta name="keywords" content="Fluids and Dynamic States (Guile Reference Manual)">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content=".texi2any-real">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="index.html" rel="start" title="Top">
<link href="Concept-Index.html" rel="index" title="Concept Index">
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
<link href="Control-Mechanisms.html" rel="up" title="Control Mechanisms">
<link href="Parameters.html" rel="next" title="Parameters">
<link href="Dynamic-Wind.html" rel="prev" title="Dynamic Wind">
<style type="text/css">
<!--
a.copiable-link {visibility: hidden; text-decoration: none; line-height: 0em}
span:hover a.copiable-link {visibility: visible}
strong.def-name {font-family: monospace; font-weight: bold; font-size: larger}
-->
</style>
<link rel="stylesheet" type="text/css" href="https://www.gnu.org/software/gnulib/manual.css">
</head>
<body lang="en">
<div class="subsection-level-extent" id="Fluids-and-Dynamic-States">
<div class="nav-panel">
<p>
Next: <a href="Parameters.html" accesskey="n" rel="next">Parameters</a>, Previous: <a href="Dynamic-Wind.html" accesskey="p" rel="prev">Dynamic Wind</a>, Up: <a href="Control-Mechanisms.html" accesskey="u" rel="up">Controlling the Flow of Program Execution</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
</div>
<hr>
<h4 class="subsection" id="Fluids-and-Dynamic-States-1"><span>6.11.11 Fluids and Dynamic States<a class="copiable-link" href="#Fluids-and-Dynamic-States-1"> &para;</a></span></h4>
<a class="index-entry-id" id="index-fluids"></a>
<p>A <em class="emph">fluid</em> is a variable whose value is associated with the dynamic
extent of a function call. In the same way that an operating system
runs a process with a given set of current input and output ports (or
file descriptors), in Guile you can arrange to call a function while
binding a fluid to a particular value. That association between fluid
and value will exist during the dynamic extent of the function call.
</p>
<p>Fluids are therefore a building block for implementing dynamically
scoped variables. Dynamically scoped variables are useful when you want
to set a variable to a value during some dynamic extent in the execution
of your program and have them revert to their original value when the
control flow is outside of this dynamic extent. See the description of
<code class="code">with-fluids</code> below for details. This association between fluids,
values, and dynamic extents is robust to multiple entries (as when a
captured continuation is invoked more than once) and early exits (for
example, when throwing exceptions).
</p>
<p>Guile uses fluids to implement parameters (see <a class="pxref" href="Parameters.html">Parameters</a>). Usually
you just want to use parameters directly. However it can be useful to
know what a fluid is and how it works, so that&rsquo;s what this section is
about.
</p>
<p>The current set of fluid-value associations can be captured in a
<em class="emph">dynamic state</em> object. A dynamic extent is simply that: a
snapshot of the current fluid-value associations. Guile users can
capture the current dynamic state with <code class="code">current-dynamic-state</code> and
restore it later via <code class="code">with-dynamic-state</code> or similar procedures.
This facility is especially useful when implementing lightweight
thread-like abstractions.
</p>
<p>New fluids are created with <code class="code">make-fluid</code> and <code class="code">fluid?</code> is
used for testing whether an object is actually a fluid. The values
stored in a fluid can be accessed with <code class="code">fluid-ref</code> and
<code class="code">fluid-set!</code>.
</p>
<p>See <a class="xref" href="Thread-Local-Variables.html">Thread-Local Variables</a>, for further notes on fluids, threads,
parameters, and dynamic states.
</p>
<dl class="first-deffn">
<dt class="deffn" id="index-make_002dfluid"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">make-fluid</strong> <var class="def-var-arguments">[dflt]</var><a class="copiable-link" href="#index-make_002dfluid"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fmake_005ffluid"><span class="category-def">C Function: </span><span><strong class="def-name">scm_make_fluid</strong> <var class="def-var-arguments">()</var><a class="copiable-link" href="#index-scm_005fmake_005ffluid"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fmake_005ffluid_005fwith_005fdefault"><span class="category-def">C Function: </span><span><strong class="def-name">scm_make_fluid_with_default</strong> <var class="def-var-arguments">(dflt)</var><a class="copiable-link" href="#index-scm_005fmake_005ffluid_005fwith_005fdefault"> &para;</a></span></dt>
<dd><p>Return a newly created fluid, whose initial value is <var class="var">dflt</var>, or
<code class="code">#f</code> if <var class="var">dflt</var> is not given.
Fluids are objects that can hold one
value per dynamic state. That is, modifications to this value are
only visible to code that executes with the same dynamic state as
the modifying code. When a new dynamic state is constructed, it
inherits the values from its parent. Because each thread normally executes
with its own dynamic state, you can use fluids for thread local storage.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-make_002dunbound_002dfluid"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">make-unbound-fluid</strong><a class="copiable-link" href="#index-make_002dunbound_002dfluid"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fmake_005funbound_005ffluid"><span class="category-def">C Function: </span><span><strong class="def-name">scm_make_unbound_fluid</strong> <var class="def-var-arguments">()</var><a class="copiable-link" href="#index-scm_005fmake_005funbound_005ffluid"> &para;</a></span></dt>
<dd><p>Return a new fluid that is initially unbound (instead of being
implicitly bound to some definite value).
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-fluid_003f"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">fluid?</strong> <var class="def-var-arguments">obj</var><a class="copiable-link" href="#index-fluid_003f"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005ffluid_005fp"><span class="category-def">C Function: </span><span><strong class="def-name">scm_fluid_p</strong> <var class="def-var-arguments">(obj)</var><a class="copiable-link" href="#index-scm_005ffluid_005fp"> &para;</a></span></dt>
<dd><p>Return <code class="code">#t</code> if <var class="var">obj</var> is a fluid; otherwise, return
<code class="code">#f</code>.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-fluid_002dref"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">fluid-ref</strong> <var class="def-var-arguments">fluid</var><a class="copiable-link" href="#index-fluid_002dref"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005ffluid_005fref"><span class="category-def">C Function: </span><span><strong class="def-name">scm_fluid_ref</strong> <var class="def-var-arguments">(fluid)</var><a class="copiable-link" href="#index-scm_005ffluid_005fref"> &para;</a></span></dt>
<dd><p>Return the value associated with <var class="var">fluid</var> in the current
dynamic root. If <var class="var">fluid</var> has not been set, then return
its default value. Calling <code class="code">fluid-ref</code> on an unbound fluid produces
a runtime error.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-fluid_002dset_0021"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">fluid-set!</strong> <var class="def-var-arguments">fluid value</var><a class="copiable-link" href="#index-fluid_002dset_0021"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005ffluid_005fset_005fx"><span class="category-def">C Function: </span><span><strong class="def-name">scm_fluid_set_x</strong> <var class="def-var-arguments">(fluid, value)</var><a class="copiable-link" href="#index-scm_005ffluid_005fset_005fx"> &para;</a></span></dt>
<dd><p>Set the value associated with <var class="var">fluid</var> in the current dynamic root.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-fluid_002dref_002a"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">fluid-ref*</strong> <var class="def-var-arguments">fluid depth</var><a class="copiable-link" href="#index-fluid_002dref_002a"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005ffluid_005fref_005fstar"><span class="category-def">C Function: </span><span><strong class="def-name">scm_fluid_ref_star</strong> <var class="def-var-arguments">(fluid, depth)</var><a class="copiable-link" href="#index-scm_005ffluid_005fref_005fstar"> &para;</a></span></dt>
<dd><p>Return the <var class="var">depth</var>th oldest value associated with <var class="var">fluid</var> in the
current thread. If <var class="var">depth</var> equals or exceeds the number of values
that have been assigned to <var class="var">fluid</var>, return the default value of the
fluid. <code class="code">(fluid-ref* f 0)</code> is equivalent to <code class="code">(fluid-ref f)</code>.
</p>
<p><code class="code">fluid-ref*</code> is useful when you want to maintain a stack-like
structure in a fluid, such as the stack of current exception handlers.
Using <code class="code">fluid-ref*</code> instead of an explicit stack allows any partial
continuation captured by <code class="code">call-with-prompt</code> to only capture the
bindings made within the limits of the prompt instead of the entire
continuation. See <a class="xref" href="Prompts.html">Prompts</a>, for more on delimited continuations.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-fluid_002dunset_0021"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">fluid-unset!</strong> <var class="def-var-arguments">fluid</var><a class="copiable-link" href="#index-fluid_002dunset_0021"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005ffluid_005funset_005fx"><span class="category-def">C Function: </span><span><strong class="def-name">scm_fluid_unset_x</strong> <var class="def-var-arguments">(fluid)</var><a class="copiable-link" href="#index-scm_005ffluid_005funset_005fx"> &para;</a></span></dt>
<dd><p>Disassociate the given fluid from any value, making it unbound.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-fluid_002dbound_003f"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">fluid-bound?</strong> <var class="def-var-arguments">fluid</var><a class="copiable-link" href="#index-fluid_002dbound_003f"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005ffluid_005fbound_005fp"><span class="category-def">C Function: </span><span><strong class="def-name">scm_fluid_bound_p</strong> <var class="def-var-arguments">(fluid)</var><a class="copiable-link" href="#index-scm_005ffluid_005fbound_005fp"> &para;</a></span></dt>
<dd><p>Returns <code class="code">#t</code> if the given fluid is bound to a value, otherwise
<code class="code">#f</code>.
</p></dd></dl>
<p><code class="code">with-fluids*</code> temporarily changes the values of one or more fluids,
so that the given procedure and each procedure called by it access the
given values. After the procedure returns, the old values are restored.
</p>
<dl class="first-deffn">
<dt class="deffn" id="index-with_002dfluid_002a"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">with-fluid*</strong> <var class="def-var-arguments">fluid value thunk</var><a class="copiable-link" href="#index-with_002dfluid_002a"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fwith_005ffluid"><span class="category-def">C Function: </span><span><strong class="def-name">scm_with_fluid</strong> <var class="def-var-arguments">(fluid, value, thunk)</var><a class="copiable-link" href="#index-scm_005fwith_005ffluid"> &para;</a></span></dt>
<dd><p>Set <var class="var">fluid</var> to <var class="var">value</var> temporarily, and call <var class="var">thunk</var>.
<var class="var">thunk</var> must be a procedure with no argument.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-with_002dfluids_002a"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">with-fluids*</strong> <var class="def-var-arguments">fluids values thunk</var><a class="copiable-link" href="#index-with_002dfluids_002a"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fwith_005ffluids"><span class="category-def">C Function: </span><span><strong class="def-name">scm_with_fluids</strong> <var class="def-var-arguments">(fluids, values, thunk)</var><a class="copiable-link" href="#index-scm_005fwith_005ffluids"> &para;</a></span></dt>
<dd><p>Set <var class="var">fluids</var> to <var class="var">values</var> temporary, and call <var class="var">thunk</var>.
<var class="var">fluids</var> must be a list of fluids and <var class="var">values</var> must be the
same number of their values to be applied. Each substitution is done
in the order given. <var class="var">thunk</var> must be a procedure with no argument.
It is called inside a <code class="code">dynamic-wind</code> and the fluids are
set/restored when control enter or leaves the established dynamic
extent.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-with_002dfluids"><span class="category-def">Scheme Macro: </span><span><strong class="def-name">with-fluids</strong> <var class="def-var-arguments">((fluid value) &hellip;) body</var><a class="copiable-link" href="#index-with_002dfluids"> &para;</a></span></dt>
<dd><p>Execute <var class="var">body</var> (see <a class="pxref" href="Local-Bindings.html">Local Variable Bindings</a>) while each <var class="var">fluid</var> is
set to the corresponding <var class="var">value</var>. Both <var class="var">fluid</var> and <var class="var">value</var>
are evaluated and <var class="var">fluid</var> must yield a fluid. The body is executed
inside a <code class="code">dynamic-wind</code> and the fluids are set/restored when
control enter or leaves the established dynamic extent.
</p></dd></dl>
<dl class="first-deftypefn">
<dt class="deftypefn" id="index-scm_005fc_005fwith_005ffluids"><span class="category-def">C Function: </span><span><code class="def-type">SCM</code> <strong class="def-name">scm_c_with_fluids</strong> <code class="def-code-arguments">(SCM fluids, SCM vals, SCM (*cproc)(void *), void *data)</code><a class="copiable-link" href="#index-scm_005fc_005fwith_005ffluids"> &para;</a></span></dt>
<dt class="deftypefnx def-cmd-deftypefn" id="index-scm_005fc_005fwith_005ffluid"><span class="category-def">C Function: </span><span><code class="def-type">SCM</code> <strong class="def-name">scm_c_with_fluid</strong> <code class="def-code-arguments">(SCM fluid, SCM val, SCM (*cproc)(void *), void *data)</code><a class="copiable-link" href="#index-scm_005fc_005fwith_005ffluid"> &para;</a></span></dt>
<dd><p>The function <code class="code">scm_c_with_fluids</code> is like <code class="code">scm_with_fluids</code>
except that it takes a C function to call instead of a Scheme thunk.
</p>
<p>The function <code class="code">scm_c_with_fluid</code> is similar but only allows one
fluid to be set instead of a list.
</p></dd></dl>
<dl class="first-deftypefn">
<dt class="deftypefn" id="index-scm_005fdynwind_005ffluid"><span class="category-def">C Function: </span><span><code class="def-type">void</code> <strong class="def-name">scm_dynwind_fluid</strong> <code class="def-code-arguments">(SCM fluid, SCM val)</code><a class="copiable-link" href="#index-scm_005fdynwind_005ffluid"> &para;</a></span></dt>
<dd><p>This function must be used inside a pair of calls to
<code class="code">scm_dynwind_begin</code> and <code class="code">scm_dynwind_end</code> (see <a class="pxref" href="Dynamic-Wind.html">Dynamic Wind</a>). During the dynwind context, the fluid <var class="var">fluid</var> is set to
<var class="var">val</var>.
</p>
<p>More precisely, the value of the fluid is swapped with a &lsquo;backup&rsquo;
value whenever the dynwind context is entered or left. The backup
value is initialized with the <var class="var">val</var> argument.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-dynamic_002dstate_003f"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">dynamic-state?</strong> <var class="def-var-arguments">obj</var><a class="copiable-link" href="#index-dynamic_002dstate_003f"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fdynamic_005fstate_005fp"><span class="category-def">C Function: </span><span><strong class="def-name">scm_dynamic_state_p</strong> <var class="def-var-arguments">(obj)</var><a class="copiable-link" href="#index-scm_005fdynamic_005fstate_005fp"> &para;</a></span></dt>
<dd><p>Return <code class="code">#t</code> if <var class="var">obj</var> is a dynamic state object;
return <code class="code">#f</code> otherwise.
</p></dd></dl>
<dl class="first-deftypefn">
<dt class="deftypefn" id="index-scm_005fis_005fdynamic_005fstate"><span class="category-def">C Procedure: </span><span><code class="def-type">int</code> <strong class="def-name">scm_is_dynamic_state</strong> <code class="def-code-arguments">(SCM obj)</code><a class="copiable-link" href="#index-scm_005fis_005fdynamic_005fstate"> &para;</a></span></dt>
<dd><p>Return non-zero if <var class="var">obj</var> is a dynamic state object;
return zero otherwise.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-current_002ddynamic_002dstate"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">current-dynamic-state</strong><a class="copiable-link" href="#index-current_002ddynamic_002dstate"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fcurrent_005fdynamic_005fstate"><span class="category-def">C Function: </span><span><strong class="def-name">scm_current_dynamic_state</strong> <var class="def-var-arguments">()</var><a class="copiable-link" href="#index-scm_005fcurrent_005fdynamic_005fstate"> &para;</a></span></dt>
<dd><p>Return a snapshot of the current fluid-value associations as a fresh
dynamic state object.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-set_002dcurrent_002ddynamic_002dstate"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">set-current-dynamic-state</strong> <var class="def-var-arguments">state</var><a class="copiable-link" href="#index-set_002dcurrent_002ddynamic_002dstate"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fset_005fcurrent_005fdynamic_005fstate"><span class="category-def">C Function: </span><span><strong class="def-name">scm_set_current_dynamic_state</strong> <var class="def-var-arguments">(state)</var><a class="copiable-link" href="#index-scm_005fset_005fcurrent_005fdynamic_005fstate"> &para;</a></span></dt>
<dd><p>Restore the saved fluid-value associations from <var class="var">state</var>, replacing
the current fluid-value associations. Return the current fluid-value
associations as a dynamic state object, as in
<code class="code">current-dynamic-state</code>.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-with_002ddynamic_002dstate"><span class="category-def">Scheme Procedure: </span><span><strong class="def-name">with-dynamic-state</strong> <var class="def-var-arguments">state proc</var><a class="copiable-link" href="#index-with_002ddynamic_002dstate"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-scm_005fwith_005fdynamic_005fstate"><span class="category-def">C Function: </span><span><strong class="def-name">scm_with_dynamic_state</strong> <var class="def-var-arguments">(state, proc)</var><a class="copiable-link" href="#index-scm_005fwith_005fdynamic_005fstate"> &para;</a></span></dt>
<dd><p>Call <var class="var">proc</var> while the fluid bindings from <var class="var">state</var> have been made
current, saving the current fluid bindings. When control leaves the
invocation of <var class="var">proc</var>, restore the saved bindings, saving instead the
fluid bindings from inside the call. If control later re-enters
<var class="var">proc</var>, restore those saved bindings, saving the current bindings,
and so on.
</p></dd></dl>
<dl class="first-deftypefn">
<dt class="deftypefn" id="index-scm_005fdynwind_005fcurrent_005fdynamic_005fstate"><span class="category-def">C Procedure: </span><span><code class="def-type">void</code> <strong class="def-name">scm_dynwind_current_dynamic_state</strong> <code class="def-code-arguments">(SCM state)</code><a class="copiable-link" href="#index-scm_005fdynwind_005fcurrent_005fdynamic_005fstate"> &para;</a></span></dt>
<dd><p>Set the current dynamic state to <var class="var">state</var> for the current dynwind
context. Like <code class="code">with-dynamic-state</code>, but in terms of Guile&rsquo;s
&ldquo;dynwind&rdquo; C API.
</p></dd></dl>
<dl class="first-deftypefn">
<dt class="deftypefn" id="index-scm_005fc_005fwith_005fdynamic_005fstate"><span class="category-def">C Procedure: </span><span><code class="def-type">void *</code> <strong class="def-name">scm_c_with_dynamic_state</strong> <code class="def-code-arguments">(SCM state, void *(*func)(void *), void *data)</code><a class="copiable-link" href="#index-scm_005fc_005fwith_005fdynamic_005fstate"> &para;</a></span></dt>
<dd><p>Like <code class="code">scm_with_dynamic_state</code>, but call <var class="var">func</var> with
<var class="var">data</var>.
</p></dd></dl>
</div>
<hr>
<div class="nav-panel">
<p>
Next: <a href="Parameters.html">Parameters</a>, Previous: <a href="Dynamic-Wind.html">Dynamic Wind</a>, Up: <a href="Control-Mechanisms.html">Controlling the Flow of Program Execution</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
</div>
</body>
</html>