add fluid->parameter
authorAndy Wingo <wingo@pobox.com>
Mon, 21 Jan 2013 10:16:29 +0000 (11:16 +0100)
committerAndy Wingo <wingo@pobox.com>
Tue, 22 Jan 2013 14:17:50 +0000 (15:17 +0100)
* 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.

doc/ref/api-scheduling.texi
module/ice-9/boot-9.scm

index 9c2b413..749583a 100644 (file)
@@ -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
index 77bb84a..a22ac8b 100644 (file)
@@ -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)