[Bese-devel] "Memoized" One time actions.
Drew Crampsie
drewc at tech.coop
Fri Feb 4 09:10:39 UTC 2005
In the midst of the great "fight for continuations" that is being waged
by the faithful on c.l.l, an infidel of unpure heart said :
> Also, if I add an entry to the clipboard, then open a new window, the
> same entry gets added again, once for each time that same URL gets
> hit. It seems that these operations or "actions" are not
> idempotent. Is that intentional?
And damnit, he was right. I don't know if UCW solves this problem, but
it wasn't hard to implement, so i fought back:
-----
(defclass memoize-component ()
((memos :initarg :memos :accessor memos :initform (make-hash-table
:test #'equalp)))
(:metaclass standard-component-class))
(defaction run-memo ((m memoize-component) fun &rest args)
(let* ((memo-id
(concatenate 'string
(ucw::find-session-id *context*)
(ucw::find-frame-id *context*)
(ucw::find-action-id *context*)))
(memo (gethash memo-id (memos m))))
(or memo
(setf (gethash memo-id (memos m)) (apply fun args)))))
(defmacro defaction-memoize (name args &body body)
(let ((fun (concatenate 'string
(string name)
"-"
(string (gensym)))))
`(progn
(defaction ,(intern fun) ,args
, at body)
(defaction ,name ,args
(run-memo ,(caar args) #',(intern fun) ,(caar args) ,@(cdr args))))))
with that done i just add the mixin to my SEARCH-BOX class, and use
DEFACTION-MEMOIZE rather than DEFACTION for any destructive actions that
manpulate global state:
(defaction-memoize add-to-clipboard ((search-box
search-box-with-clipboard) item)
(setf (clipboard search-box) (cons item (clipboard search-box))))
Which expands like to :
RR-GEO> (macroexpand-1 '(defaction-memoize add-to-clipboard ((search-box
search-box-with-clipboard) item)
(call 'info-message :message (ucw::find-action-id *context*))
(setf (clipboard search-box) (cons item (clipboard search-box)))
))
(PROGN
(DEFACTION ADD-TO-CLIPBOARD-G9697
((SEARCH-BOX SEARCH-BOX-WITH-CLIPBOARD) ITEM)
(CALL 'INFO-MESSAGE
:MESSAGE
(IT.BESE.UCW::FIND-ACTION-ID *CONTEXT*))
(SETF (CLIPBOARD SEARCH-BOX) (CONS ITEM (CLIPBOARD
SEARCH-BOX))))
(DEFACTION ADD-TO-CLIPBOARD
((SEARCH-BOX SEARCH-BOX-WITH-CLIPBOARD) ITEM)
(RUN-MEMO SEARCH-BOX #'ADD-TO-CLIPBOARD-G9697 SEARCH-BOX
ITEM)))
T
I had to create a named function because of the CPS transformer (my
first vesion used a lambda, but didn't work with actions), but it's
essentially Paul Grahams memoize macro, only keyed on a continuation id
rather than the arguments. This way the action will can be called
multiple times, just not from the exact same page.
-----
if it's desirable to have this as part of UCW proper, we could probably
do it as a method combination keyword like :
(defaction foo :memoize ((self class)) '())
And there has to be a better solution than that named function :)
Also, dolph on IRC noticed a bug in my installation, the arenida backend
is returning NIL as the http status code. I hard coded it to 200 here,
and that works fine, but is probably not desired. I don't know enough
about the backend to continue.
drewc
More information about the bese-devel
mailing list