Christophe Weblog Wiki Code Publications Music
figures
[paper-els-specializers.git] / els-specializers.org
index 3e4d250ad44d0a7994f69036ed72f77b32e459e6..74b26499fd74b009089f55494e846e088aef30f5 100644 (file)
@@ -81,6 +81,11 @@ efficient.
   incorporating substantial fractions of the Metaobject Protocol as
   described.
 
+  #+CAPTION:    MOP Design Space
+  #+LABEL:      fig:mopdesign
+  #+ATTR_LATEX: width=\linewidth float
+  [[file:figures/mop-design-space.pdf]]
+
   Although it has stood the test of time, the CLOS MOP is neither
   without issues (e.g. semantic problems with =make-method-lambda=
   \cite{Costanza.Herzeel:2008}; useful functions such as
@@ -89,12 +94,16 @@ efficient.
   implement all conceivable variations of object-oriented behaviour.
   While metaprogramming offers some possibilities for customization of
   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; 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.
+  arbitrarily in all directions (conceptually, if a given object
+  system is a point in design space, then a MOP for that object system
+  allows exploration of a region of design space around that point;
+  see figure \ref{fig:mopdesign}).  In the case of the CLOS MOP, there is
+  still an expectation that functionality is implemented with methods
+  on generic functions, 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 introspection in
@@ -104,13 +113,6 @@ efficient.
   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
-  one where an object system is a point and the MOP opens up a blob
-  around that point, and I'm sure I've seen it somewhere but I can't
-  remember where.  Alternatively, there's Kiczales et al "MOPs: why we
-  want them and what else they can do", fig. 2 ]
-  [AMOP, page 5] paints that picture, but again, only using words :)
-
   One area of functionality where there is scope for customization by
   the metaprogrammer is in the mechanics and semantics of method
   applicability and dispatch.  While in principle AMOP allows
@@ -143,8 +145,8 @@ efficient.
 
   #+CAPTION:    Dispatch Comparison
   #+LABEL:      fig:dispatch
-  #+ATTR_LATEX: width=0.9\linewidth float
-  [[file:figures/dispatch-comparison.pdf]]
+  #+ATTR_LATEX: width=\linewidth float
+  [[file:figures/dispatch-relationships.pdf]]
 
   The remaining sections in this paper can be read in any order.  We
   give some motivating examples in section [[#Examples]], including
@@ -298,9 +300,9 @@ unbound variables.
    Our second example of the implementation and use of generalized
    specializers is a reimplementation of one of the examples in
    \cite{Costanza.etal:2008}: specifically, the factorial function.
-   Here, we will perform dispatch based on the =signum= of the
+   Here, dispatch will be performed based on the =signum= of the
    argument, and again, at most one method with a =signum= specializer
-   will be appliable to any given argument, which makes the structure
+   will be applicable to any given argument, which makes the structure
    of the specializer implementation very similar to the =cons=
    specializers in the previous section.
 
@@ -361,9 +363,9 @@ unbound variables.
 (defmethod fact ((n (signum 1))) (* n (fact (1- n))))
 #+end_src
 
-   We do not need to include a method on =(signum -1)=, as the
-   standard =no-applicable-method= protocol will automatically apply to
-   negative real or non-real arguments.
+   The programmer does not need to include a method on =(signum -1)=,
+   as the standard =no-applicable-method= protocol will automatically
+   apply to negative real or non-real arguments.
 ** Accept HTTP header specializers
    :PROPERTIES:
    :CUSTOM_ID: Accept
@@ -469,7 +471,7 @@ unbound variables.
      (arg tbnl:request))
   (make-instance 'accept-generalizer
                  :header (tbnl:header-in :accept arg)
-                 :next (class-of arg)))
+                 :next (call-next-method)))
 (defmethod specializer-accepts-p
     ((s accept-specializer)
      (o tbnl:request))
@@ -486,7 +488,7 @@ unbound variables.
 (ensure-class nil :direct-superclasses
  '(text/html image/webp ...))
 #+end_src
-   and dispatch operates using those anonymous classes.  While
+   and dispatch would operate 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
@@ -496,8 +498,8 @@ unbound variables.
    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 [[#Cons]] and [[#Signum]] only a
+   non-trivial ordering of methods based on the =q= values specified
+   in the accept header (whereas in sections [[#Cons]] and [[#Signum]] only a
    single extended specializer could be applicable to any given
    argument).
 
@@ -517,7 +519,7 @@ unbound variables.
      (s string))
   (make-instance 'accept-generalizer
                  :header s
-                 :next (class-of s)))
+                 :next (call-next-method)))
 (defmethod specializer-accepts-p
     ((s accept-specializer) (o string))
   (let* ((tree (parse-accept-string o))
@@ -546,19 +548,19 @@ unbound variables.
   :END:
 
   In section [[#Examples]], we have seen a number of code fragments as
-  partial implementations of particular non-standard method dispatch,
-  using =generalizer= metaobjects to mediate between the methods of
-  the generic function and the actual arguments passed to it.  In
-  section [[#Generalizer metaobjects]], we go into more detail regarding
-  these =generalizer= metaobjects, describing the generic function
-  invocation protocol in full, and showing how this protocol allows a
-  similar form of effective method cacheing as the standard one does.
-  In section [[#Generalizer performance]], we show the results of some
-  simple performance measurements on our implementation of this
-  protocol in the SBCL implementation \cite{Rhodes:2008} of Common
-  Lisp to highlight the improvement that this protocol can bring over
-  a naïve implementation of generalized dispatch, as well as
-  to make the potential for further improvement clear.
+  partial implementations of particular non-standard method dispatch
+  strategies, using =generalizer= metaobjects to mediate between the
+  methods of the generic function and the actual arguments passed to
+  it.  In section [[#Generalizer metaobjects]], we go into more detail
+  regarding these =generalizer= metaobjects, describing the generic
+  function invocation protocol in full, and showing how this protocol
+  allows a similar form of effective method cacheing as the standard
+  one does.  In section [[#Generalizer performance]], we show the results
+  of some simple performance measurements on our implementation of
+  this protocol in the SBCL implementation \cite{Rhodes:2008} of
+  Common Lisp to highlight the improvement that this protocol can
+  bring over a naïve implementation of generalized dispatch, as well
+  as to make the potential for further improvement clear.
 
 ** Generalizer metaobjects
    :PROPERTIES:
@@ -651,8 +653,10 @@ unbound variables.
     required arguments in a list to use as a key in an =equal=
     hash-table.
 
-    [XXX could we actually compute a suitable hash key using the
+#+begin_comment
+    [could we actually compute a suitable hash key using the
     generalizer's class name and initargs?]
+#+end_comment
 
 *** COMMENT
     - [X] =generalizer-of-using-class= (NB class of gf not class of object)
@@ -809,7 +813,7 @@ unbound variables.
   cater for filtered dispatch, but they would have to explicitly
   modify their method combinations.  The Clojure programming language
   supports multimethods[fn:5] with a variant of filtered dispatch as
-  well as hierachical and identity-based method selectors.
+  well as hierarchical and identity-based method selectors.
 
   In context-oriented programming
   \cite{Hirschfeld.etal:2008,Vallejos.etal:2010}, context dispatch
@@ -874,7 +878,7 @@ unbound variables.
   amortized (though there remains a substantial overhead compared with
   standard generic-function or regular function calls).  We discuss
   how the efficiency could be improved below.
-** Future Work
+** Future work
    :PROPERTIES:
    :CUSTOM_ID: Future Work
    :END: