mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-12 06:41:13 +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-19:: Time/Date library.
|
||||||
* SRFI-26:: Specializing parameters
|
* SRFI-26:: Specializing parameters
|
||||||
* SRFI-31:: A special form `rec' for recursive evaluation
|
* SRFI-31:: A special form `rec' for recursive evaluation
|
||||||
|
* SRFI-39:: Parameter objects
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -2060,6 +2061,169 @@ The second syntax can be used to create anonymous recursive functions:
|
||||||
guile>
|
guile>
|
||||||
@end lisp
|
@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 srfi-modules.texi ends here
|
||||||
|
|
||||||
@c Local Variables:
|
@c Local Variables:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue