This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
> [PARAMETER-gizmo code omitted] That's the right idea. Maybe something like the below (modulo terminology). The other approach is to model them as single procedures that act like getters when applied to zero arguments, and setters when applied to one argument. The Guile support for this would just be a new lambda-like form that handles things nicely, and a naming convention to allow users to easily tell what procedures act this way. That's mildly cuter, but it's not existing practice. Comments solicited. define-setting NAME SETTER/GETTER Syntax Define a new `setting'. A setting represents a value to which changes and accesses must be monitored. NAME must be an identifier, and SETTER/GETTER should be an expression yielding a list of the form (SETTER GETTER). SETTER should be a procedure of one argument, called to change the value of the setting; the argument is the new value. GETTER should be a procedure of no arguments, which should return the current value of the setting. A `define-setting' form defines a pair of procedures: set-NAME! VALUE Procedure NAME Procedure set-NAME! applies SETTER to VALUE. NAME calls GETTER with no arguments. Note that a `DEFINE-SETTING' form is completely equivalent to (and more restrictive than) two ordinary DEFINE forms. The intent of the `DEFINE-SETTING' form is to establish a consistent convention for providing monitored access to variable-like entities. [What a crappy explanation. If you didn't know what it was for already, you sure wouldn't now.] `DEFINE-SETTING' accepts a list of two procedures to allow setter and getter functions to capture local variables, like `width' in the example below. This can provide some modularity, if the programmer wants that. Example: Suppose we're writing a window manager, and we want to give the user control over the width of the window borders. We cannot simply make the border width a global variable, because then user code could change the border width without notifying the window management code, and the windows' borders would not be redrawn correctly. Instead, the window manager should use `DEFINE-SETTING': (define-setting border-width (let ((width 2)) ; current value (list ;; setter function (lambda (new-width) (set! width new-width) (update-all-window-borders width)) ;; getter function (lambda () width)))) This defines two new functions, `set-border-width!' and `border-width', which can be used as follows: guile> (border-width) 2 guile> (set-border-width! 5) [all managed windows get thicker borders] guile> (border-width) 5 guile>