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]

Re: difficulty of writing translators



> [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>