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
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))
(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)
- [ ] =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
--- /dev/null
+<?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>