diff options
author | Andy Wingo <wingo@pobox.com> | 2013-01-21 11:16:29 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2013-01-22 15:17:50 +0100 |
commit | a6bd32406d952689494124de56b2d4de7cafac98 (patch) | |
tree | 961f307d6bd9da883891764ad2f2458f75f7aa00 | |
parent | 5a35d42aa5be26f1048fceea9acfa21bc9f6bc3e (diff) | |
download | guile-a6bd32406d952689494124de56b2d4de7cafac98.tar.gz |
add fluid->parameter
* module/ice-9/boot-9.scm (make-parameter): Add a docstring.
(fluid->parameter): New interface. Use it when turning port fluids
into parameters.
* doc/ref/api-scheduling.texi (Parameters): Deffn instead of defun for
make-parameter documentation. Add docs for fluid->parameter.
-rw-r--r-- | doc/ref/api-scheduling.texi | 21 | ||||
-rw-r--r-- | module/ice-9/boot-9.scm | 54 |
2 files changed, 63 insertions, 12 deletions
diff --git a/doc/ref/api-scheduling.texi b/doc/ref/api-scheduling.texi index 9c2b4132a..749583a1b 100644 --- a/doc/ref/api-scheduling.texi +++ b/doc/ref/api-scheduling.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, 2010, 2012 +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, 2010, 2012, 2013 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -869,7 +869,7 @@ 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. -@defun make-parameter init [converter] +@deffn {Scheme Procedure} make-parameter init [converter] Return a new parameter object, with initial value @var{init}. If a @var{converter} is given, then a call @code{(@var{converter} @@ -888,7 +888,7 @@ canonical form. For example, (my-param 0.75) (my-param) @result{} 3/4 @end example -@end defun +@end deffn @deffn {library syntax} parameterize ((param value) @dots{}) body1 body2 @dots{} Establish a new dynamic scope with the given @var{param}s bound to new @@ -926,6 +926,21 @@ locations. That includes the separate locations when outside any separate initial location in each dynamic state, all initialized to the given @var{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 @code{fluid->parameter} +procedure: + +@deffn {Scheme Procedure} fluid->parameter fluid [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 +@code{parameterize}, the new value will be run through the optional +@var{conv} procedure, as with any parameter. Note that unlike +@code{make-parameter}, @var{conv} is not applied to the initial value. +@end deffn + 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 diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm index 77bb84a5f..a22ac8bb5 100644 --- a/module/ice-9/boot-9.scm +++ b/module/ice-9/boot-9.scm @@ -2929,6 +2929,34 @@ but it fails to load." (set-struct-vtable-name! <parameter> '<parameter>) (define* (make-parameter init #:optional (conv (lambda (x) x))) + "Make a new parameter. + +A parameter is a dynamically bound value, accessed through a procedure. +To access the current value, apply the procedure with no arguments: + + (define p (make-parameter 10)) + (p) => 10 + +To provide a new value for the parameter in a dynamic extent, use +`parameterize': + + (parameterize ((p 20)) + (p)) => 20 + (p) => 10 + +The value outside of the dynamic extent of the body is unaffected. To +update the current value, apply it to one argument: + + (p 20) => 10 + (p) => 20 + +As you can see, the call that updates a parameter returns its previous +value. + +All values for the parameter are first run through the CONV procedure, +including INIT, the initial value. The default CONV procedure is the +identity procedure. CONV is commonly used to ensure some set of +invariants on the values that a parameter may have." (let ((fluid (make-fluid (conv init)))) (make-struct <parameter> 0 (case-lambda @@ -2938,6 +2966,22 @@ but it fails to load." prev))) fluid conv))) +(define* (fluid->parameter fluid #:optional (conv (lambda (x) x))) + "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." + (make-struct <parameter> 0 + (case-lambda + (() (fluid-ref fluid)) + ((x) (let ((prev (fluid-ref fluid))) + (fluid-set! fluid (conv x)) + prev))) + fluid conv)) + (define (parameter? x) (and (struct? x) (eq? (struct-vtable x) <parameter>))) @@ -2972,15 +3016,7 @@ but it fails to load." ;;; Current ports as parameters. ;;; -(let ((fluid->parameter - (lambda (fluid conv) - (make-struct <parameter> 0 - (case-lambda - (() (fluid-ref fluid)) - ((x) (let ((prev (fluid-ref fluid))) - (fluid-set! fluid (conv x)) - prev))) - fluid conv)))) +(let () (define-syntax-rule (port-parameterize! binding fluid predicate msg) (begin (set! binding (fluid->parameter (module-ref (current-module) 'fluid) |