A fluid 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.
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
with-fluids
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).
Guile uses fluids to implement parameters (see Parameters). 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’s what this section is about.
The current set of fluid-value associations can be captured in a
dynamic state object. A dynamic extent is simply that: a
snapshot of the current fluid-value associations. Guile users can
capture the current dynamic state with current-dynamic-state
and
restore it later via with-dynamic-state
or similar procedures.
This facility is especially useful when implementing lightweight
thread-like abstractions.
New fluids are created with make-fluid
and fluid?
is
used for testing whether an object is actually a fluid. The values
stored in a fluid can be accessed with fluid-ref
and
fluid-set!
.
See Thread-Local Variables, for further notes on fluids, threads, parameters, and dynamic states.
Return a newly created fluid, whose initial value is dflt, or
#f
if dflt 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.
Return a new fluid that is initially unbound (instead of being implicitly bound to some definite value).
Return #t
if obj is a fluid; otherwise, return
#f
.
Return the value associated with fluid in the current
dynamic root. If fluid has not been set, then return
its default value. Calling fluid-ref
on an unbound fluid produces
a runtime error.
Set the value associated with fluid in the current dynamic root.
Return the depthth oldest value associated with fluid in the
current thread. If depth equals or exceeds the number of values
that have been assigned to fluid, return the default value of the
fluid. (fluid-ref* f 0)
is equivalent to (fluid-ref f)
.
fluid-ref*
is useful when you want to maintain a stack-like
structure in a fluid, such as the stack of current exception handlers.
Using fluid-ref*
instead of an explicit stack allows any partial
continuation captured by call-with-prompt
to only capture the
bindings made within the limits of the prompt instead of the entire
continuation. See Prompts, for more on delimited continuations.
Disassociate the given fluid from any value, making it unbound.
Returns #t
if the given fluid is bound to a value, otherwise
#f
.
with-fluids*
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.
Set fluid to value temporarily, and call thunk. thunk must be a procedure with no argument.
Set fluids to values temporary, and call thunk.
fluids must be a list of fluids and values must be the
same number of their values to be applied. Each substitution is done
in the order given. thunk must be a procedure with no argument.
It is called inside a dynamic-wind
and the fluids are
set/restored when control enter or leaves the established dynamic
extent.
Execute body (see Local Variable Bindings) while each fluid is
set to the corresponding value. Both fluid and value
are evaluated and fluid must yield a fluid. The body is executed
inside a dynamic-wind
and the fluids are set/restored when
control enter or leaves the established dynamic extent.
SCM
scm_c_with_fluids (SCM fluids, SCM vals, SCM (*cproc)(void *), void *data)
¶SCM
scm_c_with_fluid (SCM fluid, SCM val, SCM (*cproc)(void *), void *data)
¶The function scm_c_with_fluids
is like scm_with_fluids
except that it takes a C function to call instead of a Scheme thunk.
The function scm_c_with_fluid
is similar but only allows one
fluid to be set instead of a list.
void
scm_dynwind_fluid (SCM fluid, SCM val)
¶This function must be used inside a pair of calls to
scm_dynwind_begin
and scm_dynwind_end
(see Dynamic Wind). During the dynwind context, the fluid fluid is set to
val.
More precisely, the value of the fluid is swapped with a ‘backup’ value whenever the dynwind context is entered or left. The backup value is initialized with the val argument.
Return #t
if obj is a dynamic state object;
return #f
otherwise.
int
scm_is_dynamic_state (SCM obj)
¶Return non-zero if obj is a dynamic state object; return zero otherwise.
Return a snapshot of the current fluid-value associations as a fresh dynamic state object.
Restore the saved fluid-value associations from state, replacing
the current fluid-value associations. Return the current fluid-value
associations as a dynamic state object, as in
current-dynamic-state
.
Call proc while the fluid bindings from state have been made current, saving the current fluid bindings. When control leaves the invocation of proc, restore the saved bindings, saving instead the fluid bindings from inside the call. If control later re-enters proc, restore those saved bindings, saving the current bindings, and so on.
void
scm_dynwind_current_dynamic_state (SCM state)
¶Set the current dynamic state to state for the current dynwind
context. Like with-dynamic-state
, but in terms of Guile’s
“dynwind” C API.
void *
scm_c_with_dynamic_state (SCM state, void *(*func)(void *), void *data)
¶Like scm_with_dynamic_state
, but call func with
data.