mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-10 22:10:21 +02:00
(SRFI-39): New section.
This commit is contained in:
parent
73222e9fa3
commit
eeadfda188
1 changed files with 164 additions and 0 deletions
|
@ -37,6 +37,7 @@ get the relevant SRFI documents from the SRFI home page
|
|||
* SRFI-19:: Time/Date library.
|
||||
* SRFI-26:: Specializing parameters
|
||||
* SRFI-31:: A special form `rec' for recursive evaluation
|
||||
* SRFI-39:: Parameter objects
|
||||
@end menu
|
||||
|
||||
|
||||
|
@ -2060,6 +2061,169 @@ The second syntax can be used to create anonymous recursive functions:
|
|||
guile>
|
||||
@end lisp
|
||||
|
||||
|
||||
@node SRFI-39
|
||||
@subsection SRFI-39 - Parameters
|
||||
@cindex SRFI-39
|
||||
@cindex parameter object
|
||||
@tindex Parameter
|
||||
|
||||
This SRFI provides parameter objects, which implement dynamically
|
||||
bound locations for values. The functions below are available from
|
||||
|
||||
@example
|
||||
(use-modules (srfi srfi-39))
|
||||
@end example
|
||||
|
||||
A parameter object is a procedure. Called with no arguments it
|
||||
returns its value, called with one argument it sets the value.
|
||||
|
||||
@example
|
||||
(define my-param (make-parameter 123))
|
||||
(my-param) @result{} 123
|
||||
(my-param 456)
|
||||
(my-param) @result{} 456
|
||||
@end example
|
||||
|
||||
The @code{parameterize} special form establishes new locations for
|
||||
parameters, those new locations having effect within the dynamic scope
|
||||
of the @code{parameterize} body. Leaving restores the previous
|
||||
locations, or re-entering through a saved continuation will again use
|
||||
the new locations.
|
||||
|
||||
@example
|
||||
(parameterize ((my-param 789))
|
||||
(my-param) @result{} 789
|
||||
)
|
||||
(my-param) @result{} 456
|
||||
@end example
|
||||
|
||||
Parameters are like dynamically bound variables in other Lisp dialets.
|
||||
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 truely limiting the
|
||||
effect of @code{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.
|
||||
|
||||
|
||||
@sp 1
|
||||
@defun make-parameter init [converter]
|
||||
Return a new parameter object, with initial value @var{init}.
|
||||
|
||||
A parameter object is a procedure. When called @code{(param)} it
|
||||
returns its value, or a call @code{(param val)} sets its value. For
|
||||
example,
|
||||
|
||||
@example
|
||||
(define my-param (make-parameter 123))
|
||||
(my-param) @result{} 123
|
||||
|
||||
(my-param 456)
|
||||
(my-param) @result{} 456
|
||||
@end example
|
||||
|
||||
If a @var{converter} is given, then a call @code{(@var{converter}
|
||||
val)} is made for each value set, its return is the value stored.
|
||||
Such a call is made for the @var{init} initial value too.
|
||||
|
||||
A @var{converter} allows values to be validated, or put into a
|
||||
canonical form. For example,
|
||||
|
||||
@example
|
||||
(define my-param (make-parameter 123
|
||||
(lambda (val)
|
||||
(if (not (number? val))
|
||||
(error "must be a number"))
|
||||
(inexact->exact val))))
|
||||
(my-param 0.75)
|
||||
(my-param) @result{} 3/4
|
||||
@end example
|
||||
@end defun
|
||||
|
||||
@deffn {library syntax} parameterize ((param value) @dots{}) body @dots{}
|
||||
Establish a new dynamic scope with the given @var{param}s bound to new
|
||||
locations and set to the given @var{value}s. @var{body} is evaluated
|
||||
in that environment, the result is the return from the last form in
|
||||
@var{body}.
|
||||
|
||||
Each @var{param} is an expression which is evaluated to get the
|
||||
parameter object. Often this will just be the name of a variable
|
||||
holding the object, but it can be anything that evaluates to a
|
||||
parameter.
|
||||
|
||||
The @var{param} expressions and @var{value} expressions are all
|
||||
evaluated before establishing the new dynamic bindings, and they're
|
||||
evaluated in an unspecified order.
|
||||
|
||||
For example,
|
||||
|
||||
@example
|
||||
(define prompt (make-parameter "Type something: "))
|
||||
(define (get-input)
|
||||
(display (prompt))
|
||||
...)
|
||||
|
||||
(parameterize ((prompt "Type a number: "))
|
||||
(get-input)
|
||||
...)
|
||||
@end example
|
||||
@end deffn
|
||||
|
||||
@deffn {Parameter object} current-input-port [new-port]
|
||||
@deffnx {Parameter object} current-output-port [new-port]
|
||||
@deffnx {Parameter object} current-error-port [new-port]
|
||||
This SRFI extends the core @code{current-input-port} and
|
||||
@code{current-output-port}, making them parameter objects. The
|
||||
Guile-specific @code{current-error-port} is extended too, for
|
||||
consistency. (@pxref{Default Ports}.)
|
||||
|
||||
This is an upwardly compatible extension, a plain call like
|
||||
@code{(current-input-port)} still returns the current input port, and
|
||||
@code{set-current-input-port} can still be used. But the port can now
|
||||
also be set with @code{(current-input-port my-port)} and bound
|
||||
dynamically with @code{parameterize}.
|
||||
@end deffn
|
||||
|
||||
@defun with-parameters* param-list value-list thunk
|
||||
Establish a new dynamic scope, as per @code{parameterize} above,
|
||||
taking parameters from @var{param-list} and corresponding values from
|
||||
@var{values-list}. A call @code{(@var{thunk})} is made in the new
|
||||
scope and the result from that @var{thunk} is the return from
|
||||
@code{with-parameters*}.
|
||||
|
||||
This function is a Guile-specific addition to the SRFI, it's similar
|
||||
to the core @code{with-fluids*} (@pxref{Fluids}).
|
||||
@end defun
|
||||
|
||||
|
||||
@sp 1
|
||||
Parameter objects are implemented using fluids (@pxref{Fluids}), so
|
||||
each dynamic root has it's own parameter locations. That includes the
|
||||
separate locations when outside any @code{parameterize} form. When a
|
||||
parameter is created it gets a separate initial location in each
|
||||
dynamic root, all initialized to the given @var{init} value.
|
||||
|
||||
As alluded to above, because each thread is a separate dynamic root,
|
||||
each thread has it's own locations behind parameter objects, and
|
||||
changes in one thread are not visible to any other. When a new
|
||||
dynamic root or thread is created, the values of parameters in the
|
||||
originating context are copied, into new locations.
|
||||
|
||||
SRFI-39 doesn't specify the interaction between parameter objects and
|
||||
threads, so the threading behaviour described here should be regarded
|
||||
as Guile-specific.
|
||||
|
||||
|
||||
@c srfi-modules.texi ends here
|
||||
|
||||
@c Local Variables:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue