[alexandria-devel] ENSUREF

Tobias C. Rittweiler tcr at freebits.de
Mon Mar 10 15:55:23 UTC 2008


ENSUREF can be used to initialize &key and &optional key args more
conveniently.

Another name would be ORF, which looks funny to my eyes.

Another name would be INITIALIZEF, but this might open questions
regarding its relation to the object initialization machinery.

  -T.


(defmacro ensuref (place thing &rest more &environment env)
  "If PLACE evaluates to NIL, set it to THING. Otherwise, let it unchanged.

Examples:

  (let ((a nil)
	(b :foo)
	(c (list 1 2 nil 4)))
    (ensuref a :a
	     b :b
	     (third c) :c)
    (values a b c))

       ==> :A, :FOO, (1 2 :C 4)

Notes:

  (ENSUREF PLACE THING) is approximately equivalent to

    (SETF PLACE (OR PLACE THING))

  except that ENSUREF ensures (no pun indented) that PLACE is
  evaluated only once, and except that PLACE isn't set at all if it
  evaluated to NIL. (E.g. as a result, auxiliary methods of (setf foo)
  generic functions aren't run in that case.)
"
  (multiple-value-bind (gvars vals gstorevars setter getter)
      (get-setf-expansion place env)
    (when (second gstorevars)
      (error "ENSUREF does not support setting multiple values ~
              via the (VALUES ...) place."))
    (if (null more)
	(let ((gstorevar (first gstorevars))
	      (gtmp (gensym "CURVAL+")))
	  `(let ,(mapcar #'list gvars vals)
	     (let ((,gtmp ,getter))
	       (if ,gtmp
		   ,gtmp
		   (let ((,gstorevar ,thing))
		     ,setter)))))
	`(progn (ensuref ,place ,thing)
		(ensuref , at more)))))




More information about the alexandria-devel mailing list