Documentation for 'swindle/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.