还有另一种方法(可能更健壮一点),您也可以轻松修改它,以便在调用回调后可以在字符串中“设置”一个字符,但我没有这样做那样是因为看起来你不需要这种能力。另外,在后一种情况下,我宁愿使用宏。
(defun mapc-words (function vector
&aux (whites '(#\Space #\Tab #\Newline #\Rubout)))
"Iterates over string `vector' and calls the `function'
with the non-white characters collected so far.
The white characters are, by default: #\Space, #\Tab
#\Newline and #\Rubout.
`mapc-words' will short-circuit when `function' returns false."
(do ((i 0 (1+ i))
(start 0)
(len 0))
((= i (1+ (length vector))))
(if (or (= i (length vector)) (find (aref vector i) whites))
(if (> len 0)
(if (not (funcall function (subseq vector start i)))
(return-from map-words)
(setf len 0 start (1+ i)))
(incf start))
(incf len))) vector)
(mapc-words
#'(lambda (word)
(not
(format t "word collected: ~s~&" word)))
"a1 b1 c1 d1 e1
a2 b2 c2 d2 e2")
;; word collected: "a1"
;; word collected: "b1"
;; word collected: "c1"
;; word collected: "d1"
;; word collected: "e1"
;; word collected: "a2"
;; word collected: "b2"
;; word collected: "c2"
;; word collected: "d2"
;; word collected: "e2"
如果您想在阅读时修改字符串,可以使用以下示例宏,但我对它并不完全满意,所以也许有人会想出更好的变体。
(defmacro with-words-in-string
((word start end
&aux (whites '(#\Space #\Tab #\Newline #\Rubout)))
s
&body body)
`(do ((,end 0 (1+ ,end))
(,start 0)
(,word)
(len 0))
((= ,end (1+ (length ,s))))
(if (or (= ,end (length ,s)) (find (aref ,s ,end) ',whites))
(if (> len 0)
(progn
(setf ,word (subseq ,s ,start ,end))
,@body
(setf len 0 ,start (1+ ,end)))
(incf ,start))
(incf len))))
(with-words-in-string (word start end)
"a1 b1 c1 d1 e1
a2 b2 c2 d2 e2"
(format t "word: ~s, start: ~s, end: ~s~&" word start end))