[cello-devel] Unbound cells

Kenny Tilton ktilton at nyc.rr.com
Wed Apr 14 07:54:14 UTC 2004



Thomas F. Burdick wrote:

>I have a couple models where I'd like to have unbound slots that
>normally have cv cells in them.  NIL is a valid value, so I can't just
>say "nil is the invalid value."  What I'm doing is using a special
>invalid-value object when I'd normally have an unbound slot:
>
>  (defconstant +unbound+ '+unbound+)
>  (deftype %nil () '(or nil (eql +unbound+)))
>
>  (defmacro define-unbound-methods (&body slot-specs)
>    (loop for (class slot opt-accessor) in slot-specs
>          for accessor = (or opt-accessor slot)
>          collect `(defmethod ,accessor :around ((object ,class))
>                     (let ((value (call-next-method)))
>                       (if (eq value +unbound+)
>                           (error 'slot-unbound :instance object :name ',slot)
>                           value)))
>          into methods
>          finally (return `(progn , at methods))))
>
>  (defun cv_ () (cv +unbound+))
>
>  (defmodel my-handler (araneida:handler)
>    ((user-id :accessor user-id :initarg user-id :initform (cv_)
>              :documentation
>              "user id or NIL if the user didn't supply valid credentials")
>     (homepage :accessor homepage :initarg homepage
>               :initform (c?_ (aif (id (^user-id))
>                                   (make-homepage-for-user id)
>                                   (create-user-account))))))
>
>  (define-unbound-methods (my-handler userid))
>
>  (defmethod handle-request-authentication ((handler my-handler) method request)
>    (setf (user-id h) ...))
>
>If user-id is unbound, it means that authentication hasn't been
>performed yet, so it would be a program error to try to use its value
>at that point.
>
>It seems like it wouldn't be too hard to put the concept of unbound
>slots into Cells itself, so that storing the unbound-slot value would
>work fine, but reading it would signal a slot-unbound error.  Add
>cell-makunbound and cell-boundp, and it would be the normal CLOS
>semantics again.
>
>Does this sound like a good idea?  Or is there a more idiomatically
>Cells way of doing this, and I'm wandering too far down The Dark Path
>of Lazyness?
>
It might be the Dark Path of a long, well-respected, misbegotten 
tradition of collapsing two attributes into one, creating /extra/ work 
to save a slot. The first of the two slots is 'sign-in-status", with 
three values: not-yet, failed, or succeeded. Then there is another slot, 
which indicates who signed in (iff successful). We programmers have a 
long heritage and habit of collapsing two values into one to save memory 
or disk space (remember those?) by using some trick such as "use nil for 
failure, unbounditude for not-yet, non-nil bound for the user", but my 
experience has been that life gets a lot easier if I just let the diff 
attributes be diff slots.

It is certainly tempting to "save one slot", but, again, my experience 
has been that the consequent overloading saves a slot at the expense of 
forever complexifying the code. I can't just say (ecase (sign-in-status 
self) (:not-yet..)(:failed..)(:cool...))... I have to detect one 
expected value with 'cell-unboundp and the other two with ecase, every 
place in the code I need to access the user.

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film 
Your Project Here! http://alu.cliki.net/Industry%20Application






More information about the cello-devel mailing list