From: Christophe Rhodes Date: Tue, 4 Mar 2014 11:17:56 +0000 (+0000) Subject: more minor corrections X-Git-Url: http://christophe.rhodes.io/gitweb/?a=commitdiff_plain;h=8ed542fa80e07826d104811350450009e4bcf036;p=paper-els-specializers.git more minor corrections --- diff --git a/els-specializers.org b/els-specializers.org index 3d426e1..a6d2bab 100644 --- a/els-specializers.org +++ b/els-specializers.org @@ -32,6 +32,8 @@ \\affaddr{Vilhonkatu 5 A}\\\\ \\affaddr{FI-00100 Helsinki}\\\\ \\email{david@lichteblau.com} +} +\\maketitle") #+end_src #+begin_abstract @@ -89,16 +91,18 @@ efficient. the object system behaviour, those possibilities cannot extend arbitrarily in all directions. There is still an expectation that functionality is implemented with methods on generic functions, - acting on objects with slots. - Example of something not doable: handling "message not understood" - message from message passing paradigm. - Nevertheless, the MOP is flexible, - and is used for a number of things, including: documentation - generation (where introspective functionality in the MOP is used to - extract information from a running system); object-relational - mapping and other approaches to object persistence; alternative - backing stores for slots (hash-tables or symbols); and programmatic - construction of metaobjects, for example for IDL compilers and model + acting on objects with slots; it is not possible, for example, to + transparently implement support for “message not understood” as in + the message-passing paradigm, because the analogue of messages + (generic functions) need to be defined before they are used. + + Nevertheless, the MOP is flexible, and is used for a number of + things, including: documentation generation (where introspective + functionality in the MOP is used to extract information from a + running system); object-relational mapping and other approaches to + object persistence; alternative backing stores for slots + (hash-tables or symbols); and programmatic construction of + metaobjects, for example for IDL compilers and model transformations. [ XXX: A picture on MOP flexibility here would be good; I have in my mind @@ -192,16 +196,16 @@ efficient. The programmer code using these specializers is unchanged from \cite{Newton.Rhodes:2008}; the benefits of the protocol described - here are centered on performance and generality: - - alternative suggestions: modularity/improved code reuse/separation - of concerns since e.g. arbitrary method combinations can be used - - in an application such as walking source code, we would expect to - encounter special forms (distinguished by particular atoms in the - =car= position) multiple times, and hence to dispatch to the same - effective method repeatedly. We discuss this in more detail in - section [[#Memoization]]; we present the metaprogrammer code below. + here are: that the separation of concerns is complete – method + selection is independent of method combination – and that the + protocol allows where possible for efficient implementation even + when method selection is customized. In an application such as + walking source code, we would expect to encounter special forms + (distinguished by particular atoms in the =car= position) multiple + times, and hence to dispatch to the same effective method + repeatedly. We discuss the efficiency aspects of the protocol in + more detail in section [[#Memoization]]; we present the metaprogrammer + code to implement the =cons-specializer= below. #+begin_src lisp (defclass cons-specializer (specializer) @@ -231,19 +235,15 @@ efficient. (and (consp o) (eql (car o) (%car s)))) #+end_src -The code above shows a minimal use of our protocol. We have -elided some support code for parsing and unparsing specializers, and -for handling introspective functions such as finding generic functions -for a given specializer. We have also elided methods on the protocol -function =specializer<= - -mention =same-specializer-p=? especially when "only one -=cons-specializer=" touches on specializer equality. - -; for =cons-specializers= here, specializer -ordering is trivial, as only one =cons-specializer= can ever be -applicable to any given argument. See section [[#Accept]] for a case -where specializer ordering is non-trivial. +The code above shows a minimal use of our protocol. We have elided +some support code for parsing and unparsing specializers, and for +handling introspective functions such as finding generic functions for +a given specializer. We have also elided methods on the protocol +functions =specializer<= and =same-specializer-p=; for +=cons-specializer= objects, specializer ordering is trivial, as only +one =cons-specializer= (up to equality) can ever be applicable to any +given argument. See section [[#Accept]] for a case where specializer +ordering is non-trivial. As in \cite{Newton.Rhodes:2008}, the programmer can use these specializers to implement a modular code walker, where they define one @@ -272,25 +272,19 @@ unbound variables. #+end_src Note that in this example there is no strict need for - =cons-specializer= and =cons-generalizer= to be distinct classes – - just as in the normal protocol involving - =compute-applicable-methods= and - =compute-applicable-methods-using-classes=, the specializer object - for mediating dispatch contains the same information as the object - representing the equivalence class of objects to which that - specializer is applicable: here it is the =car= of the =cons= - (which we wrap in a distinct object); - - the previous sentence is rather long and hard to understand - - in the standard dispatch it - is the =class= of the object. This feature also characterizes - those use cases where the metaprogrammer could straightforwardly - use filtered dispatch \cite{Costanza.etal:2008} to implement their - dispatch semantics. We will see in section [[#Accept]] an example - of a case where filtered dispatch is incapable of straightforwardly - expressing the dispatch, but first we present our implementation of - the motivating case from \cite{Costanza.etal:2008}. + =cons-specializer= and =cons-generalizer= to be distinct classes. + In standard generic function dispatch, the =class= functions both + as the specializer for methods and as the generalizer for generic + function arguments; we can think of the dispatch implemented by + =cons-specializer= objects as providing for subclasses of the + =cons= class distinguished by the =car= of the =cons=. This + analogy also characterizes those use cases where the metaprogrammer + could straightforwardly use filtered dispatch + \cite{Costanza.etal:2008} to implement their dispatch semantics. + We will see in section [[#Accept]] an example of a case where filtered + dispatch is incapable of straightforwardly expressing the dispatch, + but first we present our implementation of the motivating case from + \cite{Costanza.etal:2008}. ** SIGNUM specializers :PROPERTIES: :CUSTOM_ID: Signum @@ -304,11 +298,11 @@ unbound variables. of the specializer implementation very similar to the =cons= specializers in the previous section. - The metaprogrammer may choose to? - We have chosen to compare signum values using \texttt{=}, which - means that a method with specializer =(signum 1)= will be - applicable to positive floating-point arguments (see the first - method on =specializer-accepts-generalizer-p= and the method on + The metaprogrammer has chosen in the example below to compare + signum values using \texttt{=}, which means that a method with + specializer =(signum 1)= will be applicable to positive + floating-point arguments (see the first method on + =specializer-accepts-generalizer-p= and the method on =specializer-accepts-p= below). This leads to one subtle difference in behaviour compared to that of the =cons= specializers: in the case of =signum= specializers, the /next/ @@ -322,11 +316,10 @@ unbound variables. ((%signum :reader %signum :initarg :signum))) (defclass signum-generalizer (generalizer) ((%signum :reader %signum :initarg :signum))) -;; Not sure whether I am overlooking something but shouldn't this work: (defmethod generalizer-of-using-class ((gf signum-generic-function) (arg real)) - (make-instance 'signum-generalizer - :signum (signum arg))) + (make-instance 'signum-generalizer + :signum (signum arg))) (defmethod generalizer-equal-hash-key ((gf signum-generic-function) (g signum-generalizer)) @@ -335,18 +328,13 @@ unbound variables. ((gf signum-generic-function) (s signum-specializer) (g signum-generalizer)) - ;; Would EQL work here? I'm thinking there might be an invariant of the form - ;; (specializer-accepts-p gf o) - ;; <=> - ;; (specializer-accepts-generalizer-p gf s (generalizer-of-using-class gf o)) - ;; Or if that wrong, maybe we should explain why. - (if (= (%signum s) (%signum g)) ; or EQL? + (if (= (%signum s) (%signum g)) (values t t) (values nil t))) (defmethod specializer-accepts-generalizer-p ((gf signum-generic-function) - (s sb-mop:specializer) + (s specializer) (g signum-generalizer)) (specializer-accepts-generalizer-p gf s (class-of (%signum g)))) @@ -436,7 +424,7 @@ unbound variables. (values (q (media-type s) (tree g)) t)) (defmethod specializer-accepts-generalizer-p ((gf accept-generic-function) - (s specializer) ; other listing has sb-mop:specializer + (s specializer) (g accept-generalizer)) (specializer-accepts-generalizer-p gf s (next g))) @@ -485,9 +473,6 @@ unbound variables. (and q (> q 0)))) #+end_src - In the =next= slot in the previous listing and this listing is not - discussed, I think. - This dispatch cannot be implemented using filtered dispatch, except by generating anonymous classes with all the right mime-types as direct superclasses in dispatch order; the filter would generate @@ -533,6 +518,17 @@ unbound variables. (q (q (media-type s) tree))) (and q (> q 0)))) #+end_src + + The =next= slot in the =accept-generalizer= is present to deal with + the case of methods specialized on the classes of objects as well + as on the acceptable media types; there is a method on + =specializer-accepts-generalizer-p= for specializers that are not + of type =accept-specializer= which calls the generic function again + with the next generalizer, so that methods specialized on the + classes =tbnl:request= and =string= are treated as applicable to + corresponding objects, though less specific than methods with + =accept-specializer= specializations. + ** COMMENT Pattern / xpattern / regex / optima Here's the /really/ interesting bit, but on the other hand we're probably going to run out of space, and the full description of