From f0c5576fcf1b69076a58fd7b5440f8b9a6bba6d8 Mon Sep 17 00:00:00 2001 From: Christophe Rhodes Date: Sat, 22 Feb 2014 21:05:22 +0000 Subject: [PATCH] another train journey's worth of changes --- els-specializers.org | 114 +++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/els-specializers.org b/els-specializers.org index 59b1bd1..e2230e6 100644 --- a/els-specializers.org +++ b/els-specializers.org @@ -167,12 +167,29 @@ (and (consp o) (eql (car o) (%car s)))) #| less interesting methods elided: jmoringe: (un)parsing, specializer) (t '<)))))) +#+end_src -;; here are the only methods that actually know about TBNL +#+begin_src (defmethod generalizer-of-using-class ((gf accept-generic-function) (arg tbnl:request)) (make-instance 'accept-generalizer :header (tbnl:header-in :accept arg) @@ -357,27 +371,34 @@ est)) This dispatch can't be done with filtered dispatch, except by generating anonymous classes with all the right mime-types as - direct superclasses in dispatch order,so the filter does + direct superclasses in dispatch order; the filter would generate #+begin_src lisp (ensure-class nil :direct-superclasses '(text/html image/webp ...)) #+end_src - and dispatch is defined by using those classes. And that's even - more awkward than it sounds, because that means that in principle - all the mime types in the universe need an existence as classes, to - cater for arbitrary mime types in accept headers. And handling - wildcards is pretty much impossible, too. See that in - =specializer<= which involves a nontrivial ordering of methods - (whereas in two above previous cases only a single extended - specializer could be applicable to any given argument) - - Also of interest: note that we can have these - specializer/generalizers handle arbitrary objects: we can define - methods on =string=, completely independently from the methods on - =tbnl:request= methods are independent of each other; this - generalizes to dealing with multiple web server libraries. + and dispatch the operates using those anonymous classes. + + While this is possible to do, it is awkward to express content-type + negotiation in this way, as it means that the dispatcher must know + about the universe of mime-types that clients might declare that + they accept, rather than merely the set of mime-types that a + particular generic function is capable of serving; handling + wildcards in accept strings is particularly awkward in the + filtering paradigm. + + Note that in this example, the method on =specializer<= involves a + nontrivial ordering of methods based on the =q= values specified in + the accept header (whereas in sections XX.1 and XX.2 only a single + extended specializer could be applicable to any given argument). + + Also note that the accept specializer protocol is straightforwardly + extensible to other suitable objects; for example, one simple + debugging aid is to define that an =accept-specializer= should be + applicable to =string= objects. This can be done in a modular + fashion (see source example NN), and generalizes to dealing with + multiple web server libraries, so that content-negotiation methods + are applicable to each web server's request objects. #+begin_src lisp -;; we can define methods on STRING too, for debugging/simulation purposes (defmethod generalizer-of-using-class ((gf accept-generic-function) (s string)) (make-instance 'accept-generalizer :header s @@ -385,7 +406,6 @@ est)) (defmethod specializer-accepts-p ((s accept-specializer) (string string)) (q (media-type s) (parse-accept-string string))) #+end_src - jmoringe: the name =accept-specializer=, while sensible, may confusing in this context because "accept" occurs as part of the protocol with a different semantic. @@ -438,7 +458,7 @@ est)) think, we didn't finish the discussion regarding special variables vs. environment vs. new protocol function * Related Work - - [ ] Newton/Rhodes + - [ ] Newton/Rhodes, obv - [ ] filtered dispatch -- the point is that our work continues to be useful in cases where there are unbounded numbers of equivalence classes but each given invokation involves a small @@ -459,6 +479,18 @@ est)) fine. - [ ] Sheeple * Conclusions + - protocol for straightforward definition of custom dispatch + + interoperates seamlessly with rest of CLOS: method combination, + etc. + + tolerably efficient: two extra standard gf invokations and one + hash table lookup per call on the fast path (but more to be + done) + + expressive: handles foms of dispatch not handled elsewhere; all + the usual niceties of redefinition, modularity, introspection +** Future Work + - compute-cache-handling-functions (and general speed issues) + - automatic pattern-specializer generalizer computation + - prototype-oriented progamming a la Slate. ** Acknowledgments We thank Lee Salzman, Pascal Costanza, Mikel Evins for their helpful discussions -- 2.30.2