Subsequence Manipulations

Another set of functions allows you to manipulate subsequences of existing sequences. The most basic of these is **SUBSEQ**, which extracts a subsequence starting at a particular index and continuing to a particular ending index or the end of the sequence. For instance:

  1. (subseq "foobarbaz" 3) ==> "barbaz"
  2. (subseq "foobarbaz" 3 6) ==> "bar"

**SUBSEQ** is also **SETF**able, but it won’t extend or shrink a sequence; if the new value and the subsequence to be replaced are different lengths, the shorter of the two determines how many characters are actually changed.

  1. (defparameter *x* (copy-seq "foobarbaz"))
  2. (setf (subseq *x* 3 6) "xxx") ; subsequence and new value are same length
  3. *x* ==> "fooxxxbaz"
  4. (setf (subseq *x* 3 6) "abcd") ; new value too long, extra character ignored.
  5. *x* ==> "fooabcbaz"
  6. (setf (subseq *x* 3 6) "xx") ; new value too short, only two characters changed
  7. *x* ==> "fooxxcbaz"

You can use the **FILL** function to set multiple elements of a sequence to a single value. The required arguments are a sequence and the value with which to fill it. By default every element of the sequence is set to the value; :start and :end keyword arguments can limit the effects to a given subsequence.

If you need to find a subsequence within a sequence, the **SEARCH** function works like **POSITION** except the first argument is a sequence rather than a single item.

  1. (position #\b "foobarbaz") ==> 3
  2. (search "bar" "foobarbaz") ==> 3

On the other hand, to find where two sequences with a common prefix first diverge, you can use the **MISMATCH** function. It takes two sequences and returns the index of the first pair of mismatched elements.

  1. (mismatch "foobarbaz" "foom") ==> 3

It returns **NIL** if the strings match. **MISMATCH** also takes many of the standard keyword arguments: a :key argument for specifying a function to use to extract the values to be compared; a :test argument to specify the comparison function; and :start1, :end1, :start2, and :end2 arguments to specify subsequences within the two sequences. And a :from-end argument of **T** specifies the sequences should be searched in reverse order, causing **MISMATCH** to return the index, in the first sequence, where whatever common suffix the two sequences share begins.

  1. (mismatch "foobar" "bar" :from-end t) ==> 3