Documentation for "setf.ss"


This module provides the forms 'setf!', 'psetf!', and 'setf!-values' for generic setters, much like CL's 'setf', and 'psetf', and a form similar to MzScheme's 'set!-values'. Note that when these are later re-exported (by 'turbo'), they are renamed as 'set!', 'pset!', and 'set!-values' (overriding the built-in 'set!' and 'set!-values'). Also, note that this just defines the basic functionality, the 'misc' module defines many common setters.


(setf! place value ...) [syntax]
  Expand `(setf! (foo ...) v)' to `(set-foo! ... v)'.  The generated
  `set-foo!' identifier has the same syntax context as `foo', which
  means that to use this for some `foo' you need to define `set-foo!'
  either as a function or a syntax in the same definition context of
  `foo'.  The nice feature that comes out of this and the syntax system
  is that examples like the following work as expected:
    (let ([foo car] [set-foo! set-car!]) (setf! (foo a) 11))

  `place' gets expanded before this processing is done so macros work
  properly.  If the place is not a form, then this will just use the
  standard `set!'.

  Another extension of the original `set!' is that it allows changing
  several places in sequence -- `(setf! x a y b)' will set `x' to `a'
  and then set `y' to `b'.
(psetf! place value ...) [syntax]
  This is very similar to `setf!' above, except that the change to the
  places is done *simultaneously*.  For example, `(setf! x y y x)'
  switches the values of the two variables.
(setf!-values (place ...) expr) [syntax]
  This is a version of `setf!', that works with multiple values.  `expr'
  is expected to evaluate to the correct number of values, and these are
  then put into the specified places which can be an place suited to
  `setf!'.  Note that no duplication of identifiers is checked, if an
  identifier appears more than once then it will have the last assigned
  value.
(set-values! places ... values-expr) [syntax]
(set-list! places ... list-expr) [syntax]
(set-vector! places ... vector-expr) [syntax]
  These are defined as special forms that use `setf!-values' to set the
  given places to the appropriate components of the third form.  This
  allows foing the following:
    => (define (values a b c) (values 1 2 3))
    => (setf! (values a b c) (values 11 22 33))
    => (list a b c)
    (11 22 33)
    => (setf! (list a b c) (list 111 222 333))
    => (list a b c)
    (111 222 333)
    => (setf! (list a b c) (list 1111 2222 3333))
    => (list a b c)
    (1111 2222 3333)
  Furthermore, since the individual setting of each place is eventually
  done with `setf!', then this can be used recursively:
    => (set! (list a (vector b) (vector c c)) '(2 #(3) #(4 5)))
    => (list a b c)
    (2 3 5)
(shift! place ... newvalue) [syntax]
  This is similar to CL's `shiftf' -- it is roughly equivalent to
    (begin0 place1
            (psetf! place1 place2
                    place2 place3
                    ...
                    placen newvalue))
  except that it avoids evaluating index subforms twice, for example:
    => (let ([foo (lambda (x) (printf ">>> ~s\n" x) x)]
             [a '(1)] [b '(2)])
         (list (shift! (car (foo a)) (car (foo b)) 3) a b))
    >>> (1)
    >>> (2)
    (1 (2) (3))
(rotate! place ...) [syntax]
  This is similar to CL's `rotatef' -- it is roughly equivalent to
    (psetf! place1 place2
            place2 place3
            ...
            placen place1)
  except that it avoids evaluating index subforms twice.
(inc! place [delta]) [syntax]
(dec! place [delta]) [syntax]
(push! x place) [syntax]
(pop! place) [syntax]
  These are some simple usages of `setf!'.  Note that they also avoid
  evaluating any indexes twice.