From: Christophe Rhodes Date: Tue, 4 Mar 2014 14:36:15 +0000 (+0000) Subject: yet more minor corrections X-Git-Url: http://christophe.rhodes.io/gitweb/?a=commitdiff_plain;h=16cb673687d63345c58effb5f397cea35239c2ae;p=paper-els-specializers.git yet more minor corrections (A labmate read this and said it was comprehensible) --- diff --git a/els-specializers.org b/els-specializers.org index a6d2bab..3e4d250 100644 --- a/els-specializers.org +++ b/els-specializers.org @@ -97,13 +97,12 @@ efficient. (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. + things, including: documentation generation (where introspection 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 one where an object system is a point and the MOP opens up a blob @@ -129,10 +128,10 @@ efficient. there are no restrictions on the metaprogrammer constructing additional subclasses. Previous work \cite{Newton.Rhodes:2008} has explored the potential for customizing generic function dispatch - using extended specializers, but as of that work the metaprogrammer - must override the entirety of the generic function invocation - protocol (from =compute-discriminating-function= on down), leading - to toy implementations and duplicated effort. + using extended specializers, but there the metaprogrammer must + override the entirety of the generic function invocation protocol + (from =compute-discriminating-function= on down), leading to toy + implementations and duplicated effort. This paper introduces a protocol for efficient and controlled handling of new subclasses of =specializer=. In particular, it @@ -167,9 +166,10 @@ efficient. implemented using our protocol, which we describe in section [[#Protocol]]. For reasons of space, the metaprogram code examples in this section do not include some of the necessary support code to - run; complete implementations of each of these cases are included in - an appendix / in the accompanying repository snapshot / at this - location. + run; complete implementations of each of these cases, along with the + integration of this protocol into the SBCL implementation + \cite{Rhodes:2008} of Common Lisp, are included in an appendix / in + the accompanying repository snapshot / at this location. A note on terminology: we will attempt to distinguish between the user of an individual case of generalized dispatch (the @@ -198,7 +198,7 @@ efficient. \cite{Newton.Rhodes:2008}; the benefits of the protocol described 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 + protocol allows for efficient implementation where possible, 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 @@ -254,19 +254,25 @@ unbound variables. #+begin_src (defgeneric walk (form env stack) (:generic-function-class cons-generic-function)) -(defmethod walk ((expr (cons lambda)) env call-stack) +(defmethod walk + ((expr (cons lambda)) env call-stack) (let ((lambda-list (cadr expr)) (body (cddr expr))) (with-checked-bindings - ((bindings-from-ll lambda-list) env call-stack) + ((bindings-from-ll lambda-list) + env call-stack) (dolist (form body) (walk form env (cons form call-stack)))))) -(defmethod walk ((expr (cons let)) env call-stack) +(defmethod walk + ((expr (cons let)) env call-stack) (flet ((let-binding (x) - (walk (cadr x) env (cons (cadr x) call-stack)) - (cons (car x) (make-instance 'binding)))) + (walk (cadr x) env + (cons (cadr x) call-stack)) + (cons (car x) + (make-instance 'binding)))) (with-checked-bindings - ((mapcar #'let-binding (cadr expr)) env call-stack) + ((mapcar #'let-binding (cadr expr)) + env call-stack) (dolist (form (cddr expr)) (walk form env (cons form call-stack)))))) #+end_src @@ -376,14 +382,14 @@ unbound variables. it has available to satisfy this request, and sends the best matching resource in its response. - For example, a graphical web browser might by default send an - =Accept= header such as - =text/html,application/xml;q=0.9,*/*;q=0.8=. This should be - interpreted as meaning that if for a given resource the server can - provide content of type =text/html= (i.e. HTML), then it should do - so. Otherwise, if it can provide =application/xml= content - (i.e. XML of any schema), then that should be provided; failing - that, any other content type is acceptable. + For example, a graphical web browser might send an =Accept= header + of =text/html,application/xml;q=0.9,*/*;q=0.8= for a request of a + resource typed in to the URL bar. This should be interpreted as + meaning that: if the server can provide content of type =text/html= + (i.e. HTML) for that resource, then it should do so. Otherwise, if + it can provide =application/xml= content (i.e. XML of any schema), + then that should be provided; failing that, any other content type + is acceptable. In the case where there are static files on the filesystem, and the web server must merely select between them, there is not much more @@ -448,7 +454,7 @@ unbound variables. #+end_src The metaprogrammer can then add support for objects representing - client requesting, such as instances of the =request= class in the + client requests, such as instances of the =request= class in the Hunchentoot web server, by translating these into =accept-generalizer= instances. The code below implements this, by defining the computation of a =generalizer= object for a given @@ -519,7 +525,7 @@ unbound variables. (and q (> q 0)))) #+end_src - The =next= slot in the =accept-generalizer= is present to deal with + The =next= slot in the =accept-generalizer= is used 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 @@ -582,12 +588,12 @@ unbound variables. applicability of a particular specializer against a given argument using =specializer-accepts-p=, a new protocol function with default implementations on =class= and =eql-specializer= to - implement the expected behaviour. In order to order the methods, - as required by the protocol, we define a pairwise comparison - operator =specializer<= which defines an ordering between - specializers for a given generalizer argument (remembering that - even in standard CLOS the ordering between =class= specializers - can change depending on the actual class of the argument). + implement the expected behaviour. To order the methods, as + required by the protocol, we define a pairwise comparison operator + =specializer<= which defines an ordering between specializers for + a given generalizer argument (remembering that even in standard + CLOS the ordering between =class= specializers can change + depending on the actual class of the argument). The new =compute-applicable-methods-using-generalizers= is the analogue of the MOP's =compute-applicable-methods-using-classes=. @@ -709,7 +715,7 @@ unbound variables. answer fits in SBCL's 63-bit fixnums – in an attempt to measure the worst case for generic dispatch, where the work done within the methods is as small as possible without being meaningless, and in - particular does not cause allocation or garbage collection to + particular does not cause heap allocation or garbage collection to obscure the picture. #+begin_src lisp :exports none @@ -840,9 +846,10 @@ unbound variables. context of partial evaluation; for example, \cite{Ruf:1993} considers generalization in online partial evaluation, where sets of possible values are represented by a type system construct - representing an upper bound. The relationship between generalizer - metaobjects and approximation in type systems could be further - explored. + representing an upper bound. Exploring the relationship between + generalizer metaobjects and approximation in type systems might + yield strategies for automatically computing suitable generalizers + and cache functions for a variety of forms of generalized dispatch. * Conclusions :PROPERTIES: :CUSTOM_ID: Conclusions