]> gitweb.factorcode.org Git - factor.git/blob - core/generic/generic-docs.factor
factor: Rename GENERIC# to GENERIC#:.
[factor.git] / core / generic / generic-docs.factor
1 USING: help.markup help.syntax words classes classes.algebra
2 definitions kernel alien sequences math quotations
3 generic.single generic.standard generic.hook generic.math
4 combinators prettyprint effects ;
5 IN: generic
6
7 ARTICLE: "method-order" "Method precedence"
8 "Conceptually, method dispatch is implemented by testing the object against the predicate word for every class, in linear order (" { $link "class-linearization" } ")."
9 $nl
10 "Here is an example:"
11 { $code
12     "GENERIC: explain ( object -- )"
13     "M: object explain drop \"an object\" print ;"
14     "M: generic explain drop \"a generic word\" print ;"
15     "M: class explain drop \"a class word\" print ;"
16 }
17 "The linear order is the following, from least-specific to most-specific:"
18 { $code "{ object generic class }" }
19 "Neither " { $link class } " nor " { $link generic } " are subclasses of each other, and their intersection is non-empty. Calling " { $snippet "explain" } " with a word on the stack that is both a class and a generic word will print " { $snippet "a class word" } " because " { $link class } " is more specific than " { $link generic } " in the class linearization order. (One example of a word which is both a class and a generic word is the class of classes, " { $link class } ", which is also a word to get the class of an object.)"
20 $nl
21 "The " { $link order } " word can be useful to clarify method dispatch order:"
22 { $subsections order } ;
23
24 ARTICLE: "generic-introspection" "Generic word introspection"
25 "In most cases, generic words and methods are defined at parse time with " { $link POSTPONE: GENERIC: } " (or some other parsing word) and " { $link POSTPONE: M: } "."
26 $nl
27 "Sometimes, generic words need to be inspected or defined at run time; words for performing these tasks are found in the " { $vocab-link "generic" } " vocabulary."
28 $nl
29 "The set of generic words is a class which implements the " { $link "definition-protocol" } ":"
30 { $subsections
31     generic
32     generic?
33 }
34 "New generic words can be defined:"
35 { $subsections
36     define-generic
37     define-simple-generic
38 }
39 "Methods can be added to existing generic words:"
40 { $subsections create-method }
41 "Method definitions can be looked up:"
42 { $subsections lookup-method ?lookup-method }
43 "Finding the most specific method for an object:"
44 { $subsections effective-method }
45 "A generic word contains methods; the list of methods specializing on a class can also be obtained:"
46 { $subsections implementors }
47 "Low-level word which rebuilds the generic word after methods are added or removed, or the method combination is changed:"
48 { $subsections make-generic }
49 "Low-level method constructor:"
50 { $subsections <method> }
51 "Methods may be pushed on the stack with a literal syntax:"
52 { $subsections POSTPONE: M\ }
53 { $see-also "see" } ;
54
55 ARTICLE: "method-combination" "Custom method combination"
56 "Abstractly, a generic word can be thought of as a big chain of type conditional tests applied to the top of the stack, with methods as the bodies of each test. The " { $emphasis "method combination" } " is this control flow glue between the set of methods, and several aspects of it can be customized:"
57 { $list
58     "which stack item(s) the generic word dispatches upon,"
59     "which methods out of the set of applicable methods are called"
60 }
61 "A table of built-in method combination defining words, and the method combinations themselves:"
62 { $table
63     { { $link POSTPONE: GENERIC: } { $link standard-combination } }
64     { { $link POSTPONE: GENERIC#: } { $link standard-combination } }
65     { { $link POSTPONE: HOOK: } { $link hook-combination } }
66     { { $link POSTPONE: MATH: } { $link math-combination } }
67 }
68 "Developing a custom method combination requires that a parsing word calling " { $link define-generic } " be defined; additionally, it is a good idea to implement the " { $link "definition-protocol" } " on the class of words having this method combination, to properly support developer tools."
69 $nl
70 "The combination quotation passed to " { $link define-generic } " has stack effect " { $snippet "( word -- quot )" } ". It's job is to call various introspection words, including at least obtaining the set of methods defined on the generic word, then combining these methods in some way to produce a quotation."
71 { $see-also "generic-introspection" } ;
72
73 ARTICLE: "call-next-method" "Calling less-specific methods"
74 "If a generic word is called with an object and multiple methods specialize on classes that this object is an instance of, usually the most specific method is called (" { $link "method-order" } ")."
75 $nl
76 "Less-specific methods can be called directly:"
77 { $subsections POSTPONE: call-next-method }
78 "A lower-level word which the above expands into:"
79 { $subsections (call-next-method) }
80 "To look up the next applicable method reflectively:"
81 { $subsections next-method }
82 "Errors thrown by improper calls to " { $link POSTPONE: call-next-method } ":"
83 { $subsections
84     inconsistent-next-method
85     no-next-method
86 } ;
87
88 ARTICLE: "generic" "Generic words and methods"
89 "A " { $emphasis "generic word" } " is composed of zero or more " { $emphasis "methods" } " together with a " { $emphasis "method combination" } ". A method " { $emphasis "specializes" } " on a class; when a generic word is executed, the method combination chooses the most appropriate method and calls its definition."
90 $nl
91 "A generic word behaves roughly like a long series of class predicate conditionals in a " { $link cond } " form, however methods can be defined in independent source files, reducing coupling and increasing extensibility. The method combination determines which object the generic word will " { $emphasis "dispatch" } " on; this could be the top of the stack, or some other value."
92 $nl
93 "Generic words which dispatch on the object at the top of the stack:"
94 { $subsections POSTPONE: GENERIC: }
95 "A method combination which dispatches on a specified stack position:"
96 { $subsections POSTPONE: GENERIC#: }
97 "A method combination which dispatches on the value of a variable at the time the generic word is called:"
98 { $subsections POSTPONE: HOOK: }
99 "A method combination which dispatches on a pair of stack values, which must be numbers, and upgrades both to the same type of number:"
100 { $subsections POSTPONE: MATH: }
101 "Method definition:"
102 { $subsections POSTPONE: M: }
103 "Generic words must declare their stack effect in order to compile. See " { $link "effects" } "."
104 { $subsections
105     "method-order"
106     "call-next-method"
107     "method-combination"
108     "generic-introspection"
109 }
110 "Generic words specialize behavior based on the class of an object; sometimes behavior needs to be specialized on the object's " { $emphasis "structure" } "; this is known as " { $emphasis "pattern matching" } " and is implemented in the " { $vocab-link "match" } " vocabulary." ;
111
112 ABOUT: "generic"
113
114 HELP: generic
115 { $class-description "The class of generic words, documented in " { $link "generic" } "." } ;
116
117 { generic define-generic define-simple-generic POSTPONE: GENERIC: POSTPONE: GENERIC#: POSTPONE: MATH: POSTPONE: HOOK: } related-words
118
119 HELP: make-generic
120 { $values { "word" generic } }
121 { $description "Regenerates the definition of a generic word by applying the method combination to the set of defined methods." }
122 $low-level-note ;
123
124 HELP: define-generic
125 { $values { "word" word } { "combination" "a method combination" } { "effect" effect } }
126 { $description "Defines a generic word. A method combination is an object which responds to the " { $link perform-combination } " generic word." }
127 { $contract "The method combination quotation is called each time the generic word has to be updated (for example, when a method is added), and thus must be side-effect free." } ;
128
129 HELP: M\
130 { $syntax "M\\ class generic" }
131 { $description "Pushes a method on the stack." }
132 { $examples { $code "M\\ fixnum + see" } { $code "USING: ui.gadgets.editors ui.render ;" "M\\ editor draw-gadget* edit" } } ;
133
134 HELP: method
135 { $class-description "The class of method bodies, which are words with special word properties set." } ;
136
137 HELP: lookup-method
138 { $values { "class" class } { "generic" generic } { "method" method } }
139 { $description "Looks up a method definition." }
140 { $errors "Throws an error if the method does not exist." } ;
141
142 HELP: ?lookup-method
143 { $values { "class" class } { "generic" generic } { "method/f" { $maybe method } } }
144 { $description "Looks up a method definition." } ;
145
146 { lookup-method ?lookup-method create-method POSTPONE: M: } related-words
147
148 HELP: <method>
149 { $values { "class" class } { "generic" generic } { "method" "a new method definition" } }
150 { $description "Creates a new method." } ;
151
152 HELP: order
153 { $values { "generic" generic } { "seq" { $sequence class } } }
154 { $description "Outputs a sequence of classes for which methods have been defined on this generic word. The sequence is sorted in method dispatch order." } ;
155
156 HELP: check-method
157 { $values { "class" class } { "generic" generic } }
158 { $description "Asserts that " { $snippet "class" } " is a class word and " { $snippet "generic" } " is a generic word, throwing a " { $link check-method } " error if the assertion fails." }
159 { $error-description "Thrown if " { $link POSTPONE: M: } " or " { $link create-method } " is given an invalid class or generic word." } ;
160
161 HELP: with-methods
162 { $values { "class" class } { "generic" generic } { "quot" { $quotation ( methods -- ) } } }
163 { $description "Applies a quotation to the generic word's methods hashtable, and regenerates the generic word's definition when the quotation returns." }
164 $low-level-note ;
165
166 HELP: create-method
167 { $values { "class" class } { "generic" generic } { "method" method } }
168 { $description "Creates a method or returns an existing one. This is the runtime equivalent of " { $link POSTPONE: M: } "." }
169 { $notes "To define a method, pass the output value to " { $link define } "." } ;
170
171 { sort-classes order } related-words
172
173 HELP: (call-next-method)
174 { $values { "method" method } }
175 { $description "Low-level word implementing " { $link POSTPONE: call-next-method } "." }
176 { $notes
177     "The " { $link POSTPONE: call-next-method } " word parses into this word. The following are equivalent:"
178     { $code
179         "M: class generic call-next-method ;"
180         "M: class generic M\\ class generic (call-next-method) ;"
181     }
182 } ;
183
184 HELP: no-next-method
185 { $error-description "Thrown by " { $link POSTPONE: call-next-method } " if the current method is already the least specific method." }
186 { $examples
187     "The following code throws this error:"
188     { $code
189         "GENERIC: error-test ( object -- )"
190         ""
191         "M: number error-test 3 + call-next-method ;"
192         ""
193         "M: integer error-test recip call-next-method ;"
194         ""
195         "123 error-test"
196     }
197     "This results in the method on " { $link integer } " being called, which then calls the method on " { $link number } ". The latter then calls " { $link POSTPONE: call-next-method } ", however there is no method less specific than the method on " { $link number } " and so an error is thrown."
198 } ;