<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:times new roman, new york, times, serif;font-size:12pt"><div>Hello all,<br><br>I propose that the types for easy-handlers be extensible by the users.  I have pieces of markup which are used throughout our site which collect information from several fields into a class (in our case tied to a database with clsql).  The names of the fields are related, but diffierent from the lists, arrays and hashes of the easy-handlers,  Dates and addresses are two good examples, but there are others.  I would like to be able to teach the easy handler to collect these for me and pass them as parameters.  This cannot be done with functions as the :parameter-type because the functions passed as :parameter-type do not take the parameter name.<br><br>There are two ways I think this could be done:<br><br>- The easier way: add a :paramater-reader arg to the parameter
 description, and if passed use it in lieu of the ((post|get)-)?parameter functions in compute-parameter. The following might do it (untested):<br><br>(defun compute-parameter (parameter-name parameter-type request-type <br>                                            &optional parameter-reader)   ; <=====<br>  "Computes and returns the parameter\(s) called PARAMETER-NAME<br>and converts it/them according to the value of PARAMETER-TYPE.<br>REQUEST-TYPE is one of :GET, :POST, or :BOTH."<br>  (when (member parameter-type '(list array hash-table))<br>    (setq parameter-type (list parameter-type 'string)))<br>  (let ((parameter-reader (or parameter-reader   ;
 <====<br>                           (ecase request-type<br>                              (:get #'get-parameter)<br>                              (:post #'post-parameter)<br>                              (:both #'parameter)))        )<br>        (parameters (and (listp
 parameter-type)<br>                         (case request-type<br>                           (:get (get-parameters))<br>                           (:post (post-parameters))<br>                           (:both (append (get-parameters) (post-parameters)))))))<br>    (cond ((atom parameter-type)<br>           (compute-simple-parameter parameter-name parameter-type
 parameter-reader))<br>          ((and (null (cddr parameter-type))<br>                (eq (first parameter-type) 'list))<br>           (compute-list-parameter parameter-name (second parameter-type) parameters))<br>          ((and (null (cddr parameter-type))<br>                (eq (first parameter-type) 'array))<br>           (compute-array-parameter parameter-name (second parameter-type) parameters))<br>          ((and (null (cddddr parameter-type))<br>                (eq (first parameter-type)
 'hash-table))<br>           (compute-hash-table-parameter parameter-name (second parameter-type) parameters<br>                                         (or (third parameter-type) 'string)<br>                                         (or (fourth parameter-type) 'equal)))<br>          (t (error "Don't know what to do with parameter type ~S." parameter-type)))))<br><br>(defun make-defun-parameter (description default-parameter-type default-request-type)<br>  "Creates a keyword parameter
 to be used by DEFINE-EASY-HANDLER.<br>DESCRIPTION is one of the elements of DEFINE-EASY-HANDLER's<br>LAMBDA-LIST and DEFAULT-PARAMETER-TYPE and DEFAULT-REQUEST-TYPE<br>are the global default values."<br>  (when (atom description)<br>    (setq description (list description)))<br>  (destructuring-bind (parameter-name &key (real-name (compute-real-name parameter-name))<br>                                           parameter-type init-form request-type      parameter-reader   )         ; <====<br>      description<br>    `(,parameter-name (or (and (boundp
 '*request*)<br>                               (compute-parameter ,real-name<br>                                                  ,(or parameter-type default-parameter-type)<br>                                                  ,(or request-type
 default-request-type)))<br>                          ,init-form))))<br><br>(This just occurred to me: request-type could be a function, with an obvious change to the ecase.  This is a little more confusing but consistent with what parameter-type does---so it has the force of precedent---and requires a smaller change to the code.).<br><br>- The extensive way:   Change the  cond in compute-parameter to a switch via a hash table, whose values are the conversion handlers (or a cons with reader and converter).  It may need two hash tables: one for simple type names (type is a symbol) and one for aggregates, (type is a cons, and switch on the first element).  Create a macro, define-easy-type, or something, to populate the tables, and use it within easy-handlers.lisp to populate it with those which are now hardcoded in the cond
 and case switches.  Users can then use the macro to define their own types.<br><br>- Another way: like above, but use methods instead of hash tables.  This seems possible, but I'd have to think some more about it.<br><br><br>BTW: why the checks for null CDDRs and CDDDDRs in compute-parameter?  Is this just nice, or are they essential?<br><br>If your interested in the second, I will work something up and send in a patch.  I do not think it would break any existing code which did not peak too far into the easy-handlers stuff.<br><br>Let me know what you think.<br><br>Tim S<br><br>P.S.:<br>Hunchentoot is a pleasure to work with!<br> </div></div></body></html>