]> gitweb.factorcode.org Git - factor.git/blob - core/classes/tuple/tuple-docs.factor
e16be25ce4314c517caaedccfe307d13f7ea4681
[factor.git] / core / classes / tuple / tuple-docs.factor
1 USING: generic help.markup help.syntax kernel
2 classes.tuple.private classes slots quotations words arrays
3 generic.standard sequences definitions compiler.units
4 growable vectors sbufs assocs math ;
5 IN: classes.tuple
6
7 ARTICLE: "slot-read-only-declaration" "Read-only slots"
8 "By default, all slots are writable. If a slot is explicitly declared " { $link read-only } ", then no writer method is generated for the slot, and the only way to set it to a value other than its initial value is to construct an instance of the tuple with " { $link boa } ", passing the initial value for the read-only slot on the stack; the common idiom of calling " { $link new } " and then immediately filling in slot values with setter words will not work with read-only slots." ;
9
10 ARTICLE: "slot-class-declaration" "Slot class declarations"
11 "Class declaration is optional, and the default value is " { $link object } ", the class of all objects. If a more specific class is declared, then the object system maintains an invariant that the value of the slot must always be an instance of the class, even during construction. This invariant is enforced at a number of locations:"
12 { $list
13     { "Writer words (" { $link "accessors" } ") throw an error if the new value does not satisfy the class predicate." }
14     { "The " { $link new } " word fills in slots with their initial values; the (per-class) initial values are required to satisfy the class predicate." }
15     { "The " { $link boa } " word ensures that the values on the stack satisfy the class predicate." }
16     { { $link "mirrors" } " ensure that the value passed to " { $link set-at } " satisfies the class predicate." }
17     { "The " { $link slots>tuple } " and " { $link >tuple } " words ensure that the values in the sequence satisfy the correct class predicates." }
18     { { $link "tuple-redefinition" } " fills in new slots with initial values and ensures that changes to existing declarations result in incompatible values being replaced with the initial value of their respective slots." }
19 }
20 { $subsection "slot-class-coercion" } ;
21
22 ARTICLE: "slot-class-coercion" "Coercive slot declarations"
23 "If the class of a slot is declared to be one of " { $link fixnum } " or " { $link float } ", then rather than testing values with the class predicate, writer words coerce values to the relevant type with " { $link >fixnum } " or " { $link >float } ". This may still result in error, but permits a wider range of values than a class predicate test. It also results in a possible loss of precision; for example, storing a large integer into a " { $link fixnum } " slot will silently overflow and discard high bits, and storing a ratio into a " { $link float } " slot may lose precision if the ratio is one which cannot be represented exactly with floating-point."
24 $nl
25 "This feature is mostly intended as an optimization for low-level code designed to avoid integer overflow, or where floating point precision is sufficient. Most code needs to work transparently with large integers, and thus hsould avoid the coercion behavior by using " { $link integer } " and " { $link real } " in place of " { $link fixnum } " and " { $link float } "." ;
26
27 ARTICLE: "tuple-declarations" "Tuple slot declarations"
28 "The slot specifier syntax of the " { $link POSTPONE: TUPLE: } " parsing word understands the following slot attributes:"
29 { $list
30     "class declaration: values must satisfy the class predicate"
31     { "whether a slot is read only or not (" { $link read-only } ")" }
32     { "an initial value (" { $link initial: } ")" }
33 }
34 { $subsection "slot-read-only-declaration" }
35 { $subsection "slot-class-declaration" }
36 { $subsection "slot-initial-values" } ;
37
38 ARTICLE: "parametrized-constructors" "Parameterized constructors"
39 "A " { $emphasis "parametrized constructor" } " is a word which directly or indirectly calls " { $link new } " or " { $link boa } ", but instead of passing a literal class symbol, it takes the class symbol as an input from the stack."
40 $nl
41 "Parametrized constructors are useful in many situations, in particular with subclassing. For example, consider the following code:"
42 { $code
43     "TUPLE: vehicle max-speed occupants ;"
44     ""
45     ": add-occupant ( person vehicle -- ) occupants>> push ;"
46     ""
47     "TUPLE: car < vehicle engine ;"
48     ": <car> ( max-speed engine -- car )"
49     "    car new"
50     "        V{ } clone >>occupants"
51     "        swap >>engine"
52     "        swap >>max-speed ;"
53     ""
54     "TUPLE: aeroplane < vehicle max-altitude ;"
55     ": <aeroplane> ( max-speed max-altitude -- aeroplane )"
56     "    aeroplane new"
57     "        V{ } clone >>occupants"
58     "        swap >>max-altitude"
59     "        swap >>max-speed ;"
60 }
61 "The two constructors depend on the implementation of " { $snippet "vehicle" } " because they are responsible for initializing the " { $snippet "occupants" } " slot to an empty vector. If this slot is changed to contain a hashtable instead, there will be two places instead of one. A better approach is to use a parametrized constructor for vehicles:"
62 { $code
63     "TUPLE: vehicle max-speed occupants ;"
64     ""
65     ": add-occupant ( person vehicle -- ) occupants>> push ;"
66     ""
67     ": new-vehicle ( class -- vehicle )"
68     "    new"
69     "        V{ } clone >>occupants ;"
70     ""
71     "TUPLE: car < vehicle engine ;"
72     ": <car> ( max-speed engine -- car )"
73     "    car new-vehicle"
74     "        swap >>engine"
75     "        swap >>max-speed ;"
76     ""
77     "TUPLE: aeroplane < vehicle max-altitude ;"
78     ": <aeroplane> ( max-speed max-altitude -- aeroplane )"
79     "    aeroplane new-vehicle"
80     "        swap >>max-altitude"
81     "        swap >>max-speed ;"
82 }
83 "The naming convention for parametrized constructors is " { $snippet "new-" { $emphasis "class" } } "." ;
84
85 ARTICLE: "tuple-constructors" "Tuple constructors"
86 "Tuples are created by calling one of two constructor primitives:"
87 { $subsection new }
88 { $subsection boa }
89 "A shortcut for defining BOA constructors:"
90 { $subsection POSTPONE: C: }
91 "By convention, construction logic is encapsulated in a word named after the tuple class surrounded in angle brackets; for example, the constructor word for a " { $snippet "point" } " class might be named " { $snippet "<point>" } "."
92 $nl
93 "Constructors play a part in enforcing the invariant that slot values must always match slot declarations. The " { $link new } " word fills in the tuple will initial values, and " { $link boa } " ensures that the values on the stack match the corresponding slot declarations. See " { $link "tuple-declarations" } "."
94 $nl
95 "All tuple construction should be done through constructor words, and construction primitives should be encapsulated and never called outside of the vocabulary where the class is defined, because this encourages looser coupling. For example, a constructor word could be changed to use memoization instead of always constructing a new instance, or it could be changed to construt a different class, without breaking callers."
96 $nl
97 "Examples of constructors:"
98 { $code
99     "TUPLE: color"
100     "{ red integer }"
101     "{ green integer }"
102     "{ blue integer }"
103     "{ alpha integer initial: 1 } ;"
104     ""
105     "! The following two are equivalent"
106     "C: <rgba> rgba"
107     ": <rgba> color boa ;"
108     ""
109     "! We can define constructors which call other constructors"
110     ": <rgb> 1 <rgba> ;"
111     ""
112     "! The following two are equivalent; note the initial value"
113     ": <color> ( -- color ) color new ;"
114     ": <color> ( -- color ) 0 0 0 1 <rgba> ;"
115     "! Run-time error"
116     "\"not a number\" 2 3 4 color boa"
117 }
118 { $subsection "parametrized-constructors" } ;
119
120 ARTICLE: "tuple-inheritance-example" "Tuple subclassing example"
121 "Rectangles, parallelograms and circles are all shapes. We support two operations on shapes:"
122 { $list
123     "Computing the area"
124     "Computing the perimiter"
125 }
126 "Rectangles and parallelograms use the same algorithm for computing the area, whereas they use different algorithms for computing perimiter. Also, rectangles and parallelograms both have " { $snippet "width" } " and " { $snippet "height" } " slots. We can exploit this with subclassing:"
127 { $code
128     "GENERIC: area ( shape -- n )"
129     "GENERIC: perimiter ( shape -- n )"
130     ""
131     "TUPLE: shape ;"
132     ""
133     "TUPLE: circle < shape radius ;"
134     "M: area circle radius>> sq pi * ;"
135     "M: perimiter circle radius>> 2 * pi * ;"
136     ""
137     "TUPLE: quad < shape width height"
138     "M: area quad [ width>> ] [ height>> ] bi * ;"
139     ""
140     "TUPLE: rectangle < quad ;"
141     "M: rectangle perimiter [ width>> 2 * ] [ height>> 2 * ] bi + ;"
142     ""
143     ": hypot ( a b -- c ) [ sq ] bi@ + sqrt ;"
144     ""
145     "TUPLE: parallelogram < quad skew ;"
146     "M: parallelogram perimiter"
147     "    [ width>> 2 * ] [ [ height>> ] [ skew>> ] bi hypot 2 * ] bi + ;"
148 } ;
149
150 ARTICLE: "tuple-inheritance-anti-example" "When not to use tuple subclassing"
151 "Tuple subclassing should only be used for " { $emphasis "is-a" } " relationships; for example, a car " { $emphasis "is a" } " vehicle, and a circle " { $emphasis "is a" } " shape."
152 { $heading "Anti-pattern #1: subclassing for has-a" }
153 "Subclassing should not be used for " { $emphasis "has-a" } " relationships. For example, if a shape " { $emphasis "has a" } " color, then " { $snippet "shape" } " should not subclass " { $snippet "color" } ". Using tuple subclassing in inappropriate situations leads to code which is more brittle and less flexible than it should be."
154 $nl
155 "For example, suppose that " { $snippet "shape" } " inherits from " { $snippet "color" } ":"
156 { $code
157     "TUPLE: color r g b ;"
158     "TUPLE: shape < color ... ;"
159 }
160 "Now, the implementation of " { $snippet "shape" } " depends on a specific representation of colors as RGB colors. If a new generic color protocol is devised which also allows HSB and YUV colors to be used, the shape class will not be able to take advantage of them without changes. A better approach is to store the color in a slot:"
161 { $code
162     "TUPLE: rgb-color r g b ;"
163     "TUPLE: hsv-color h s v ;"
164     "..."
165     "TUPLE: shape color ... ;"
166 }
167 "The " { $vocab-link "delegate" } " library provides a language abstraction for expressing has-a relationships."
168 { $heading "Anti-pattern #2: subclassing for implementation sharing only" }
169 "Tuple subclassing purely for sharing implementations of methods is not a good idea either. If a class " { $snippet "A" } " is a subclass of a class " { $snippet "B" } ", then instances of " { $snippet "A" } " should be usable anywhere that an instance of " { $snippet "B" } " is. If this properly does not hold, then subclassing should not be used."
170 $nl
171 "There are two alternatives which are preferred to subclassing in this case. The first is " { $link "mixins" } "."
172 $nl
173 "The second is to use ad-hoc slot polymorphism. If two classes define a slot with the same name, then code which uses " { $link "accessors" } " can operate on instances of both objects, assuming the values stored in that slot implement a common protocol. This allows code to be shared without creating contrieved relationships between classes."
174 { $heading "Anti-pattern #3: subclassing to override a method definition" }
175 "While method overriding is a very powerful tool, improper use can cause tight coupling of code and lead to difficulty in testing and refactoring. Subclassing should not be used as a means of ``monkey patching'' methods to fix bugs and add features. Only subclass from classes which were designed to be inherited from, and when writing classes of your own which are intended to be subclassed, clearly document that subclasses may and may not do. This includes construction policy; document whether subclasses should use " { $link new } ", " { $link boa } ", or a custom parametrized constructor."
176 { $see-also "parametrized-constructors" } ;
177
178 ARTICLE: "tuple-subclassing" "Tuple subclassing"
179 "Tuple subclassing can be used to express natural relationships between classes at the language level. For example, every car " { $emphasis "is a" } " vehicle, so if the " { $snippet "car" } " class subclasses the " { $snippet "vehicle" } " class, it can " { $emphasis "inherit" } " the slots and methods of " { $snippet "vehicle" } "."
180 $nl
181 "To define one tuple class as a subclass of another, use the optional superclass parameter to " { $link POSTPONE: TUPLE: } ":"
182 { $code
183     "TUPLE: subclass < superclass ... ;"
184 }
185 { $subsection "tuple-inheritance-example" }
186 { $subsection "tuple-inheritance-anti-example" } 
187 { $see-also "call-next-method" "parametrized-constructors" "unions" "mixins" } ;
188
189 ARTICLE: "tuple-introspection" "Tuple introspection"
190 "In addition to the slot reader and writer words which " { $link POSTPONE: TUPLE: } " defines for every tuple class, it is possible to construct and take apart entire tuples in a generic way."
191 { $subsection >tuple }
192 { $subsection tuple>array }
193 { $subsection tuple-slots }
194 "Tuple classes can also be defined at run time:"
195 { $subsection define-tuple-class }
196 { $see-also "slots" "mirrors" } ;
197
198 ARTICLE: "tuple-examples" "Tuple examples"
199 "An example:"
200 { $code "TUPLE: employee name salary position ;" }
201 "This defines a class word named " { $snippet "employee" } ", a predicate " { $snippet "employee?" } ", and the following slot accessors:"
202 { $table
203     { "Reader" "Writer" "Setter" "Changer" }
204     { { $snippet "name>>" }    { $snippet "(>>name)" }    { $snippet ">>name" }    { $snippet "change-name" }    }
205     { { $snippet "salary>>" } { $snippet "(>>salary)" } { $snippet ">>salary" } { $snippet "change-salary" } }
206     { { $snippet "position>>" }   { $snippet "(>>position)" }   { $snippet ">>position" }   { $snippet "change-position" }   }
207 }
208 "We can define a constructor which makes an empty employee:"
209 { $code ": <employee> ( -- employee )"
210     "    employee new ;" }
211 "Or we may wish the default constructor to always give employees a starting salary:"
212 { $code
213     ": <employee> ( -- employee )"
214     "    employee new"
215     "        40000 >>salary ;"
216 }
217 "We can define more refined constructors:"
218 { $code
219     ": <manager> ( -- manager )"
220     "    <employee> \"project manager\" >>position ;" }
221 "An alternative strategy is to define the most general BOA constructor first:"
222 { $code
223     ": <employee> ( name position -- person )"
224     "    40000 employee boa ;"
225 }
226 "Now we can define more specific constructors:"
227 { $code
228     ": <manager> ( name -- person )"
229     "    \"manager\" <person> ;" }
230 "An example using reader words:"
231 { $code
232     "TUPLE: check to amount number ;"
233     ""
234     "SYMBOL: checks"
235     ""
236     ": <check> ( to amount -- check )"
237     "    checks counter check boa ;"
238     ""
239     ": biweekly-paycheck ( employee -- check )"
240     "    dup name>> swap salary>> 26 / <check> ;"
241 }
242 "An example of using a changer:"
243 { $code
244     ": positions"
245     "    {"
246     "        \"junior programmer\""
247     "        \"senior programmer\""
248     "        \"project manager\""
249     "        \"department manager\""
250     "        \"executive\""
251     "        \"CTO\""
252     "        \"CEO\""
253     "        \"enterprise Java world dictator\""
254     "    } ;"
255     ""
256     ": next-position ( role -- newrole )"
257     "    positions [ index 1+ ] keep nth ;"
258     ""
259     ": promote ( person -- person )"
260     "    [ 1.2 * ] change-salary"
261     "    [ next-position ] change-position ;"
262 }
263 "An example using subclassing can be found in " { $link "tuple-inheritance-example" } "." ;
264
265 ARTICLE: "tuple-redefinition" "Tuple redefinition"
266 "In the following, the " { $emphasis "direct slots" } " of a tuple class refers to the slot names specified in the " { $link POSTPONE: TUPLE: } " form defining the tuple class, and the " { $emphasis "effective slots" } " refers to the concatenation of the direct slots together with slots defined on superclasses."
267 $nl
268 "When the " { $emphasis "effective slots" } " of a tuple class change, all instances of the class, including subclasses, are updated."
269 $nl
270 "There are three ways in which the list of effective slots may change:"
271 { $list
272     "Adding or removing direct slots of the class"
273     "Adding or removing direct slots of a superclass of the class"
274     "Changing the inheritance hierarchy by changing the superclass of a class"
275     "Declarations changing on existing slots"
276 }
277 "In all cases, the new effective slots are compared with the old effective slots, and each instance is updated as follows:"
278 { $list
279     "If any slots were removed, the values are removed from the instance and are lost forever."
280     "If any slots were added, the instance gains these slots, all set to their initial values."
281     "If any slots are permuted, their values in instances do not change; only the layout of the instance changes in memory."
282     "If the slot declaration of an existing slot changes, existing values are checked to see if they are still an instance of the required class. Any which are not are replaced by the initial value of that slot."
283     "If the number or order of effective slots changes, any BOA constructors are recompiled."
284 }
285 "Note that if a slot is moved from a class to its superclass (or vice versa) in the same compilation unit, the value of the slot is preserved in existing instances, because tuple instance update always runs at the end of a compilation unit. However, if it is removed in one compilation unit and added in another, the value in existing instances is lost." ;
286
287 ARTICLE: "protocol-slots" "Protocol slots"
288 "A " { $emphasis "protocol slot" } " is one which is assumed to exist by the implementation of a class, without being defined on the class itself. The burden is on subclasses (or mixin instances) to provide this slot."
289 $nl
290 "Protocol slots are defined using a parsing word:"
291 { $subsection POSTPONE: SLOT: }
292 "Protocol slots are used where the implementation of a superclass needs to assume that each subclass defines certain slots, however the slots of each subclass are potentially declared with different class specializers, thus preventing the slots from being defined in the superclass."
293 $nl
294 "For example, the " { $link growable } " mixin provides an implementation of the sequence protocol which wraps an underlying sequence, resizing it as necessary when elements are added beyond the length of the sequence. It assumes that the concrete mixin instances define two slots, " { $snippet "length" } " and " { $snippet "underlying" } ". These slots are defined as protocol slots:"
295 { $snippet "SLOT: length" "SLOT: underlying" }
296 "An alternate approach would be to define " { $link growable } " as a tuple class with these two slots, and have other classes subclass it as required. However, this rules out subclasses defining these slots with custom type declarations."
297 $nl
298 "For example, compare the definitions of the " { $link sbuf } " class,"
299 { $code
300     "TUPLE: sbuf"
301     "{ underlying string }"
302     "{ length array-capacity } ;"
303     ""
304     "INSTANCE: sbuf growable"
305 }
306 "with that of the " { $link vector } " class:"
307 { $code
308     "TUPLE: vector"
309     "{ underlying array }"
310     "{ length array-capacity } ;"
311     ""
312     "INSTANCE: vector growable"
313 } ;
314
315 ARTICLE: "tuples" "Tuples"
316 "Tuples are user-defined classes composed of named slots. They are the central data type of Factor's object system."
317 { $subsection "tuple-examples" }
318 "A parsing word defines tuple classes:"
319 { $subsection POSTPONE: TUPLE: }
320 "For each tuple class, several words are defined, the class word, a class predicate, and accessor words for each slot."
321 $nl
322 "The class word is used for defining methods on the tuple class; it has the same name as the tuple class. The predicate is named " { $snippet { $emphasis "name" } "?" } ". Initially, no specific words are defined for constructing new instances of the tuple. Constructors must be defined explicitly, and tuple slots are accessed via automatically-generated accessor words."
323 { $subsection "accessors" }
324 { $subsection "tuple-constructors" }
325 { $subsection "tuple-subclassing" }
326 { $subsection "tuple-declarations" }
327 { $subsection "protocol-slots" }
328 { $subsection "tuple-introspection" }
329 "Tuple classes can be redefined; this updates existing instances:"
330 { $subsection "tuple-redefinition" }
331 "Tuple literal syntax is documented in " { $link "syntax-tuples" } "." ;
332
333 ABOUT: "tuples"
334
335 HELP: tuple-class
336 { $class-description "The class of tuple class words." }
337 { $examples { $example "USING: classes.tuple prettyprint ;" "IN: scratchpad" "TUPLE: name title first last ;" "name tuple-class? ." "t" } } ;
338
339 HELP: tuple=
340 { $values { "tuple1" tuple } { "tuple2" tuple } { "?" "a boolean" } }
341 { $description "Low-level tuple equality test. User code should use " { $link = } " instead." }
342 { $warning "This word is in the " { $vocab-link "classes.tuple.private" } " vocabulary because it does not do any type checking. Passing values which are not tuples can result in memory corruption." } ;
343
344 HELP: tuple
345 { $class-description "The class of tuples. This class is further partitioned into disjoint subclasses; each tuple shape defined by " { $link POSTPONE: TUPLE: } " is a new class."
346 $nl
347 "Tuple classes have additional word properties:"
348 { $list
349     { { $snippet "\"predicate\"" } " - a quotation which tests if the top of the stack is an instance of this tuple class" }
350     { { $snippet "\"slots\"" } " - a sequence of " { $link slot-spec } " instances" }
351     { { $snippet "\"tuple-layout\"" } " - a " { $link tuple-layout } " instance" }
352 } } ;
353
354 HELP: define-tuple-predicate
355 { $values { "class" tuple-class } }
356 { $description "Defines a predicate word that tests if the top of the stack is an instance of " { $snippet "class" } ". This will only work if " { $snippet "class" } " is a tuple class." }
357 $low-level-note ;
358
359 HELP: redefine-tuple-class
360 { $values { "class" class } { "superclass" class } { "slots" "a sequence of strings" } }
361 { $description "If the new slot layout differs from the existing one, updates all existing instances of this tuple class, and forgets any slot accessor words which are no longer needed."
362 $nl
363 "If the class is not a tuple class word, this word does nothing." }
364 $low-level-note ;
365
366 HELP: tuple-slots
367 { $values { "tuple" tuple } { "seq" sequence } }
368 { $description "Pushes a sequence of tuple slot values, not including the tuple class word." } ;
369
370 { tuple-slots tuple>array } related-words
371
372 HELP: define-tuple-slots
373 { $values { "class" tuple-class } }
374 { $description "Defines slot accessor and mutator words for the tuple." }
375 $low-level-note ;
376
377 HELP: check-tuple
378 { $values { "class" class } }
379 { $description "Throws a " { $link check-tuple } " error if " { $snippet "word" } " is not a tuple class word." }
380 { $error-description "Thrown if " { $link POSTPONE: C: } " is called with a word which does not name a tuple class." } ;
381
382 HELP: define-tuple-class
383 { $values { "class" word } { "superclass" class } { "slots" "a sequence of strings" } }
384 { $description "Defines a tuple class inheriting from " { $snippet "superclass" } " with slots named by " { $snippet "slots" } ". This is the run time equivalent of " { $link POSTPONE: TUPLE: } "." }
385 { $notes "This word must be called from inside " { $link with-compilation-unit } "." }
386 { $side-effects "class" } ;
387
388 { tuple-class define-tuple-class POSTPONE: TUPLE: } related-words
389
390 HELP: >tuple
391 { $values { "seq" sequence } { "tuple" tuple } }
392 { $description "Creates a tuple with slot values taken from a sequence. The first element of the sequence must be a tuple class word and the remainder the declared slots."
393 $nl
394 "If the sequence has too few elements, the remaining slots in the tuple are set to their initial values." }
395 { $errors "Throws an error if one of the following occurs:"
396     { $list
397         "the first element of the sequence is not a tuple class word"
398         "the values in the sequence do not satisfy the slot class predicates"
399         "the sequence is too long"
400     }
401 } ;
402
403 HELP: tuple>array ( tuple -- array )
404 { $values { "tuple" tuple } { "array" array } }
405 { $description "Outputs an array having the tuple's slots as elements. The first element is the tuple class word and remainder are declared slots." } ;
406
407 HELP: <tuple> ( layout -- tuple )
408 { $values { "layout" tuple-layout } { "tuple" tuple } }
409 { $description "Low-level tuple constructor. User code should never call this directly, and instead use " { $link new } "." } ;
410
411 HELP: <tuple-boa> ( ... layout -- tuple )
412 { $values { "..." "values" } { "layout" tuple-layout } { "tuple" tuple } }
413 { $description "Low-level tuple constructor. User code should never call this directly, and instead use " { $link boa } "." } ;
414
415 HELP: new
416 { $values { "class" tuple-class } { "tuple" tuple } }
417 { $description "Creates a new instance of " { $snippet "class" } " with all slots set to their initial values (see" { $link "tuple-declarations" } ")." }
418 { $examples
419     { $example
420         "USING: kernel prettyprint ;"
421         "IN: scratchpad"
422         "TUPLE: employee number name department ;"
423         "employee new ."
424         "T{ employee }"
425     }
426 } ;
427
428 HELP: boa
429 { $values { "..." "slot values" } { "class" tuple-class } { "tuple" tuple } }
430 { $description "Creates a new instance of " { $snippet "class" } " and fill in the slots from the stack, with the top-most stack element being stored in the right-most slot." }
431 { $notes "The name " { $snippet "boa" } " is shorthand for ``by order of arguments'', and ``BOA constructor'' is a pun on ``boa constrictor''." }
432 { $errors "Throws an error if the slot values do not match class declarations on slots (see" { $link "tuple-declarations" } ")." } ;