Common Lisp the Language, 2nd Edition

Next: Optimization Up: Series Functions Previous: Collectors

## A.2.6. Alteration of Series

Series that come from scanning data structures such as lists and vectors are closely linked to these structures. The function `alter` can be used to modify the underlying data structure with reference to the series derived from it. (Conversely, it is possible to modify a series by destructively modifying the data structure it is derived from. However, given the lazy evaluation nature of series, the effects of such modifications can be very hard to predict. As a result, this kind of modification is inadvisable.)

[Function]
`alter destinations items`

`alter` changes the series destinations so that it contains the elements in the series items. More importantly, in the manner of `setf`, the data structure that underlies destinations is changed so that if the series destinations were to be regenerated, the new values would be obtained. The alteration process stops as soon as either input runs out of elements. The value `nil` is always returned. In the example below each negative element in a list is replaced with its square.

    (let* ((data (list 1 -2 3 4 -5 6))
           (x (choose-if #'minusp (scan data))))
      (alter x (#M* x x))
      data)
      => (1 4 3 4 25 6)

`alter` can be applied only to series that are alterable. `scan`, `scan-alist`, `scan-multiple`, `scan-plist`, and `scan-lists-of-lists-fringe` produce alterable series. However, the alterability of the output of `scan-lists-of-lists-fringe` is incomplete. If `scan-lists-of-lists-fringe` is applied to an object that is a leaf, altering the output series does not change the object.

In general, the output of a transducer is alterable as long as the elements of the output come directly from the elements of an input that is alterable. In particular, the outputs of `choose`, `choose-if`, `split`, `split-if`, `cotruncate`, `until`, `until-if`, and `subseries` are alterable as long as the corresponding inputs are alterable.

[Function]
`to-alter items alter-fn &rest args`

Given a series items, `to-alter` returns an alterable series A containing the same elements. The argument alter-fn is a function. The remaining arguments are all series. Let these series be S1, ..., Sn. If there are n arguments after alter-fn, alter-fn must accept n+1 inputs. If `(alter A B)` is later encountered, the expression `(map-fn t alter-fn B S1 ... Sn)` is implicitly evaluated. For each element in B, alter-fn should make appropriate changes in the data structure underlying A.

As an example, consider the following definition of a series function that scans the elements of a list. Alteration is performed by changing cons cells in the list being scanned.

    (defun scan-list (list)
      (declare (optimizable-series-function))
      (let ((sublists (scan-sublists list)))
        (to-alter (#Mcar sublists)
                  #'(lambda (new parent) (setf (car parent) new))
                  sublists)))

Next: Optimization Up: Series Functions Previous: Collectors