#:stringify #:mappend #:listify #:fix-pair #:pairify #:parse-body
#:whitespace-char-p
#:slot-uninitialized
- #:nlet #:while #:until #:case2 #:ecase2
+ #:nlet #:while #:until #:case2 #:ecase2 #:setf-default
#:with-gensyms #:let*/gensyms #:with-places
#:locp #:locf #:ref #:with-locatives
#:update-place #:update-place-after
"Like `case2', but signals an error if no clause matches the SCRUTINEE."
(do-case2-like 'ecase vform clauses))
+(defmacro setf-default (&rest specs &environment env)
+ "Like setf, but only sets places which are currently nil.
+
+ The arguments are an alternating list of PLACEs and DEFAULTs. If a PLACE
+ is nil, the DEFAULT is evaluated and stored in the PLACE; otherwise the
+ default is /not/ stored. The result is the (new) value of the last
+ PLACE."
+ (labels ((doit (specs)
+ (cond ((null specs) nil)
+ ((null (cdr specs))
+ (error "Odd number of arguments for SETF-DEFAULT."))
+ (t
+ (let ((place (car specs))
+ (default (cadr specs))
+ (rest (cddr specs)))
+ (multiple-value-bind
+ (vars vals store-vals writer reader)
+ (get-setf-expansion place env)
+ `(let* ,(mapcar #'list vars vals)
+ (or ,reader
+ (multiple-value-bind ,store-vals ,default
+ ,writer))
+ ,@(and rest (list (doit rest))))))))))
+ (doit specs)))
+
;;;--------------------------------------------------------------------------
;;; with-places
if RADIX is nil. Returns two values: the integer parsed (or nil if there
wasn't enough for a sensible parse), and the index following the
characters of the integer."
- (unless end (setf end (length string)))
+ (setf-default end (length string))
(labels ((simple (i r goodp sgn)
(multiple-value-bind
(a i)
(flet ((emit ()
(write-string string stream :start start :end i)
(setf start i)))
- (unless end
- (setf end (length string)))
+ (setf-default end (length string))
(loop
(unless (< i end)
(emit)
If QUOTEDP, then allow quoting and backslashifying; otherwise don't. The
START and END arguments limit the portion of the string to be processed;
the default to 0 and nil (end of string), as usual."
- (unless start (setf start 0))
- (unless end (setf end (length string)))
+ (setf-default start 0 end (length string))
(let ((i start)
(q nil)
(e nil)