]> rhodes.io Git - paper-els-specializers.git/commitdiff
Christophe Weblog Wiki Code Publications Music
comments and figure from Jan
authorChristophe Rhodes <csr21@cantab.net>
Thu, 6 Feb 2014 08:11:59 +0000 (08:11 +0000)
committerChristophe Rhodes <csr21@cantab.net>
Thu, 6 Feb 2014 08:11:59 +0000 (08:11 +0000)
els-specializers.org
figures/dispatch-comparison.pdf [new file with mode: 0644]
figures/dispatch-comparison.svg [new file with mode: 0644]

index 6af13922e89061170f1e4e46ca20a85379664924..d9b66cf7c23e3d83e68274bf46a2a631e33fba54 100644 (file)
   Paepke; AMOP?].  XXX include typical examples of MOP: object
   persistence; maybe ref. Kizcales "MOPs: why we want them and what
   else they can do"? (Fig. 2 in that is good) ORMs; sparse slots.
+  jmoringe:
+  + introspection, e.g. documentation generation
+  + programmatic construction of classes and generic functions
+    e.g. for IDL compilers, model transformations
 
   One area of functionality where there is scope for customization by
   the metaprogrammer is in the mechanics and semantics of method
@@ -59,6 +63,8 @@
   practice implementation support for this was weak until relatively
   recently (ref. closer, also check how ContextL and filtered dispatch
   are implemented).
+  jmoringe: filtered dispatch uses a custom method combination, i
+  think
 
   Another potential mechanism for customizing dispatch is implicit in
   the class structure defined by AMOP: standard specializer objects
   (ahem) the return value of =class-of=, and allows the metaprogrammer
   to hook into cacheing schemes to avoid needless recomputation of
   effective methods for sufficiently similar generic function
-  arguments.
+  arguments (See Figure\nbsp\ref{fig:dispatch}).
+
+  #+CAPTION:    Dispatch Comparison
+  #+LABEL:      fig:dispatch
+  #+ATTR_LATEX: width=0.9\linewidth float
+  [[file:figures/dispatch-comparison.pdf]]
 
   The remaining sections in this paper can be read in any order.  We
   give some motivating examples in section XX, including
 (defmethod specializer-accepts-p ((s cons-specializer) o)
   (and (consp o) (eql (car o) (%car s))))
 
-#| less interesting methods elided |#
+#| less interesting methods elided: jmoringe: (un)parsing, specializer<?, more? |#
 
 #| XXX insert motivating example from Newton/Rhodes here |#
 #+end_src
    specializer could be applicable to any given argument)
 
    Also of interest: note that we can have these
-   specializer/generalizers handle arbitrary objects: the string and
-   tbnl:request methods are independent of each other; this
+   specializer/generalizers handle arbitrary objects: the =string= and
+   =tbnl:request= methods are independent of each other; this
    generalizes to dealing with multiple web server libraries.
+
+   jmoringe: the name =accept-specializer=, while sensible, may
+   confusing in this context because "accept" occurs as part of the
+   protocol with a different semantic.
+
 #+begin_src lisp
 (defclass accept-specializer (extended-specializer)
   ((media-type :initarg :media-type :reader media-type)))
    (next :initarg :next :reader next)))
 (defmethod generalizer-equal-hash-key
     ((gf accept-generic-function) (g accept-generalizer))
-  `(accept-generalizer ,(header g)))
+   `(accept-generalizer ,(header g)))
 (defmethod specializer-accepts-generalizer-p ((gf accept-generic-function) (s acc
 ept-specializer) (generalizer accept-generalizer))
   (values (q (media-type s) (tree generalizer)) t))
@@ -235,12 +251,18 @@ est))
 (defmethod specializer-accepts-p ((s accept-specializer) (string string))
   (q (media-type s) (parse-accept-string string)))
 #+end_src
+
+   jmoringe: The role of =accept-generalizer.tree= and the =q=
+   function are hard to understand and may require some
+   explanation. However, the example with its distinct, asymmetric
+   specializers/generalizers, =accept-generalizer.next= and
+   =specializer<= is likely worth it.
+
 ** 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
-   these is going to take us into make-method-lambda territory.  A
-   second paper?  Future work?  It would be really nice to put a
-   marker in the sand.
+   these is going to take us into =make-method-lambda= territory.
+   A second paper?  Future work?
 * Protocol
 ** Generalizer
    - [ ] =generalizer-of-using-class= (NB class of gf not class of object)
@@ -249,12 +271,41 @@ est))
    - [ ] =specializer-accepts-generalizer-p=
    - [ ] =specializer-accepts-p=
    - [ ] =specializer<=
+     jmoringe: If I remember correctly, closette has
+     =method-more-specific-p= should we aim for parity with that and
+     use =specializer-more-specific-p=? The downside would be that
+     =-p= indicates a Boolean return value which is not the case here.
 ** Full protocol
    Description and specification left for reasons of space (we'll see?)
    - [ ] =same-specializer-p=
    - [ ] =parse/unparse-specializer-using-class=
    - [ ] =make-method-specializers-form=
+   - [ ] jmoringe: In an email, I suggested
+     =make-specializer-form-using-class=:
+
+     #+begin_quote
+     Could we change =make-method-specializers-form='s default
+     behaviour to call a new generic function
+     #+begin_src
+       make-specializer-form-using-class gf method name env
+     #+end_src
+     with builtin methods on =sb-mop:specializer=, =symbol=, =cons= (for
+     eql-specializers)? This would make it unnecessary to repeat
+     boilerplate along the lines of
+     #+begin_src lisp
+     (flet ((make-parse-form (name)
+              (if <name-is-interesting>
+                <handle-interesting-specializer>
+                <repeat-handling-of-standard-specializers>)))
+       `(list ,@(mapcar #'make-parse-form specializer-names)))
+     #+end_src
+     for each generic function class.
+     #+end_quote
    - [ ] =make-method-lambda= revision (use environment arg?)
+
+     jmoringe: would only be relevant for pattern dispatch, right? I
+     think, we didn't finish the discussion regarding special
+     variables vs. environment vs. new protocol function
 * Related Work
   - [ ] Newton/Rhodes
   - [ ] filtered dispatch
diff --git a/figures/dispatch-comparison.pdf b/figures/dispatch-comparison.pdf
new file mode 100644 (file)
index 0000000..9a29d1d
Binary files /dev/null and b/figures/dispatch-comparison.pdf differ
diff --git a/figures/dispatch-comparison.svg b/figures/dispatch-comparison.svg
new file mode 100644 (file)
index 0000000..292c5de
--- /dev/null
@@ -0,0 +1,515 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="856.98193"
+   height="234.33665"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.3.1 r9886"
+   sodipodi:docname="dispatch-comparision.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="EmptyTriangleInL"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="EmptyTriangleInL"
+       style="overflow:visible">
+      <path
+         id="path4073"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,4.8,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="647.09412"
+     inkscape:cy="38.998487"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:snap-global="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1920"
+     inkscape:window-height="1151"
+     inkscape:window-x="1440"
+     inkscape:window-y="24"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(27.665546,-26.452583)">
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+       x="95.253151"
+       y="41.647896"
+       id="text2985"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2987"
+         x="95.253151"
+         y="41.647896">AMOP Dispatch</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+       x="514.53345"
+       y="41.647896"
+       id="text2989"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2991"
+         x="514.53345"
+         y="41.647896">Generalized Dispatch</tspan></text>
+    <g
+       id="g4464">
+      <g
+         transform="translate(385.42857,49.857143)"
+         id="g3801">
+        <rect
+           y="130.79225"
+           x="319.40588"
+           height="28.139849"
+           width="105.2827"
+           id="rect3803"
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <text
+           sodipodi:linespacing="125%"
+           id="text3805"
+           y="149.03015"
+           x="332.4613"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           xml:space="preserve"><tspan
+             y="149.03015"
+             x="332.4613"
+             id="tspan3807"
+             sodipodi:role="line">Argument</tspan></text>
+      </g>
+      <g
+         transform="translate(166.92857,-66.642857)"
+         id="g3809">
+        <rect
+           y="130.79225"
+           x="319.40588"
+           height="28.139849"
+           width="105.2827"
+           id="rect3811"
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <text
+           sodipodi:linespacing="125%"
+           id="text3813"
+           y="149.03015"
+           x="328.05896"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           xml:space="preserve"><tspan
+             y="149.03015"
+             x="328.05896"
+             id="tspan3815"
+             sodipodi:role="line">Specializer</tspan></text>
+      </g>
+      <g
+         id="g3822"
+         transform="translate(385.92857,-1.642857)">
+        <rect
+           style="fill:none;stroke:#ff0000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect3824"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="325.41833"
+           y="149.03015"
+           id="text3826"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan3828"
+             x="325.41833"
+             y="149.03015">Generalizer</tspan></text>
+      </g>
+      <g
+         id="g3859"
+         transform="translate(234.42857,-1.642857)">
+        <rect
+           style="fill:none;stroke:#ff0000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect3861"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="329.13708"
+           y="149.03015"
+           id="text3863"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan3865"
+             x="329.13708"
+             y="149.03015">Gen. Spec.</tspan></text>
+      </g>
+      <g
+         inkscape:connector-avoid="true"
+         id="g3867"
+         transform="translate(170.60223,49.857143)">
+        <rect
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect3869"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="350.93005"
+           y="149.03015"
+           id="text3871"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan3873"
+             x="350.93005"
+             y="149.03015">Class</tspan></text>
+      </g>
+      <g
+         id="g3875"
+         transform="translate(94.42857,101.35714)">
+        <g
+           id="g3897">
+          <rect
+             y="130.79225"
+             x="319.40588"
+             height="28.139849"
+             width="105.2827"
+             id="rect3877"
+             style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+          <text
+             sodipodi:linespacing="125%"
+             id="text3879"
+             y="149.03015"
+             x="334.84802"
+             style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+             xml:space="preserve"><tspan
+               y="149.03015"
+               x="334.84802"
+               id="tspan3881"
+               sodipodi:role="line">Eql-Spec.</tspan></text>
+        </g>
+      </g>
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3859"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3822"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="polyline"
+         id="path3883"
+         d="m 705.33445,143.21932 -46.2173,0"
+         style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3801"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3822"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3885"
+         d="m 757.9758,157.28924 0,23.36015"
+         style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3801"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3875"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3887"
+         d="m 519.11715,246.21932 235.35865,0 c 1.5,0 3,-1.5 3,-3 l 0,-34.43008"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3867"
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3801"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3889"
+         d="m 595.29081,194.71932 109.54364,0"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3867"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3809"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3891"
+         d="m 542.64946,92.289243 0,88.360147"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL)" />
+      <path
+         inkscape:connection-end="#g3875"
+         inkscape:connection-end-point="d4"
+         sodipodi:nodetypes="cssc"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3809"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3893"
+         d="m 486.33445,78.219319 -16.85865,0 c -1.5,0 -3,1.5 -3,3 l 0,150.930071"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL)" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3859"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3809"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3895"
+         d="m 591.61715,78.219319 11.85865,0 c 1.5,0 3,1.5 3,3 l 0,47.930071"
+         style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL)" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text3902"
+         y="191.86218"
+         x="610.5"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="191.86218"
+           x="610.5"
+           id="tspan3904"
+           sodipodi:role="line">match class-of</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3906"
+         y="243.36218"
+         x="615.5"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="243.36218"
+           x="615.5"
+           id="tspan3908"
+           sodipodi:role="line">match</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3910"
+         y="139.36218"
+         x="664.5"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="139.36218"
+           x="664.5"
+           id="tspan3912"
+           sodipodi:role="line">s-a-g-p</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3914"
+         y="172.36218"
+         x="760"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="172.36218"
+           x="760"
+           id="tspan3916"
+           sodipodi:role="line">generalizer-of</tspan></text>
+    </g>
+    <g
+       id="g4506">
+      <g
+         id="g4364"
+         transform="translate(-55.57143,49.857143)">
+        <rect
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect4366"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="332.4613"
+           y="149.03015"
+           id="text4368"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan4370"
+             x="332.4613"
+             y="149.03015">Argument</tspan></text>
+      </g>
+      <g
+         id="g4372"
+         transform="translate(-308.4846,-66.642857)">
+        <rect
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect4374"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="328.05896"
+           y="149.03015"
+           id="text4376"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan4378"
+             x="328.05896"
+             y="149.03015">Specializer</tspan></text>
+      </g>
+      <g
+         transform="translate(-270.39777,49.857143)"
+         id="g4396"
+         inkscape:connector-avoid="true">
+        <rect
+           y="130.79225"
+           x="319.40588"
+           height="28.139849"
+           width="105.2827"
+           id="rect4398"
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <text
+           sodipodi:linespacing="125%"
+           id="text4400"
+           y="149.03015"
+           x="350.93005"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           xml:space="preserve"><tspan
+             y="149.03015"
+             x="350.93005"
+             id="tspan4402"
+             sodipodi:role="line">Class</tspan></text>
+      </g>
+      <g
+         transform="translate(-346.57143,101.35714)"
+         id="g4404">
+        <g
+           id="g4406">
+          <rect
+             style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+             id="rect4408"
+             width="105.2827"
+             height="28.139849"
+             x="319.40588"
+             y="130.79225" />
+          <text
+             xml:space="preserve"
+             style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+             x="334.84802"
+             y="149.03015"
+             id="text4410"
+             sodipodi:linespacing="125%"><tspan
+               sodipodi:role="line"
+               id="tspan4412"
+               x="334.84802"
+               y="149.03015">Eql-Spec.</tspan></text>
+        </g>
+      </g>
+      <path
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 78.117153,246.21932 235.358647,0 c 1.5,0 3,-1.5 3,-3 l 0,-34.43008"
+         id="path4418"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3" />
+      <path
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+         d="m 154.29081,194.71932 109.54364,0"
+         id="path4420"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3" />
+      <path
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g4372"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL);display:inline"
+         d="m 101.64946,92.289243 0,88.360147"
+         id="path4422"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3" />
+      <path
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g4372"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL);display:inline"
+         d="m 25.4758,92.289243 0,139.860147"
+         id="path4424"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3"
+         sodipodi:nodetypes="cssc" />
+      <text
+         xml:space="preserve"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         x="169.5"
+         y="191.86218"
+         id="text4428"
+         sodipodi:linespacing="125%"><tspan
+           sodipodi:role="line"
+           id="tspan4430"
+           x="169.5"
+           y="191.86218">match class-of</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         x="174.5"
+         y="243.36218"
+         id="text4432"
+         sodipodi:linespacing="125%"><tspan
+           sodipodi:role="line"
+           id="tspan4434"
+           x="174.5"
+           y="243.36218">match</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+       x="659.33447"
+       y="68.789238"
+       id="text4533"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4535"
+         x="659.33447"
+         y="68.789238">specializer-accepts-generalizer-p</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 714,46.336655 704,106.33665"
+       id="path4537"
+       inkscape:connector-curvature="0"
+       transform="translate(-27.665546,26.452583)" />
+  </g>
+</svg>