The parameterize special form establishes new locations for
parameters, those new locations having effect within the dynamic scope
of the parameterize body. Leaving restores the previous
locations. Re-entering (through a saved continuation) will again use
the new locations.

(parameterize ((my-param 789))
(my-param)) ⇒ 789
(my-param) ⇒ 456

Parameters are like dynamically bound variables in other Lisp dialects.
They allow an application to establish parameter settings (as the name
suggests) just for the execution of a particular bit of code, restoring
when done. Examples of such parameters might be case-sensitivity for a
search, or a prompt for user input.

Global variables are not as good as parameter objects for this sort of
thing. Changes to them are visible to all threads, but in Guile
parameter object locations are per-thread, thereby truly limiting the
effect of parameterize to just its dynamic execution.

Passing arguments to functions is thread-safe, but that soon becomes
tedious when there’s more than a few or when they need to pass down
through several layers of calls before reaching the point they should
affect. And introducing a new setting to existing code is often easier
with a parameter object than adding arguments.

Scheme Procedure: make-parameterinit [converter]

Return a new parameter object, with initial value init.

If a converter is given, then a call (converter
val) is made for each value set, its return is the value stored.
Such a call is made for the init initial value too.

A converter allows values to be validated, or put into a
canonical form. For example,

Parameter objects are implemented using fluids (see Fluids and Dynamic States), so each dynamic state has its own parameter
locations. That includes the separate locations when outside any
parameterize form. When a parameter is created it gets a
separate initial location in each dynamic state, all initialized to the
given init value.

New code should probably just use parameters instead of fluids, because
the interface is better. But for migrating old code or otherwise
providing interoperability, Guile provides the fluid->parameter
procedure:

Scheme Procedure: fluid->parameterfluid [conv]

Make a parameter that wraps a fluid.

The value of the parameter will be the same as the value of the fluid.
If the parameter is rebound in some dynamic extent, perhaps via
parameterize, the new value will be run through the optional
conv procedure, as with any parameter. Note that unlike
make-parameter, conv is not applied to the initial value.

As alluded to above, because each thread usually has a separate dynamic
state, each thread has its own locations behind parameter objects, and
changes in one thread are not visible to any other. When a new dynamic
state or thread is created, the values of parameters in the originating
context are copied, into new locations.