]> gitweb.factorcode.org Git - factor.git/blob - core/classes/tuple/tuple-docs.factor
Language change: tuple slot setter words with stack effect ( value object -- ) are...
[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 { $subsections "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 should 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 { $subsections
35     "slot-read-only-declaration"
36     "slot-class-declaration"
37     "slot-initial-values"
38 } ;
39
40 ARTICLE: "parametrized-constructors" "Parameterized constructors"
41 "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."
42 $nl
43 "Parametrized constructors are useful in many situations, in particular with subclassing. For example, consider the following code:"
44 { $code
45     "TUPLE: vehicle max-speed occupants ;"
46     ""
47     ": add-occupant ( person vehicle -- ) occupants>> push ;"
48     ""
49     "TUPLE: car < vehicle engine ;"
50     ": <car> ( max-speed engine -- car )"
51     "    car new"
52     "        V{ } clone >>occupants"
53     "        swap >>engine"
54     "        swap >>max-speed ;"
55     ""
56     "TUPLE: aeroplane < vehicle max-altitude ;"
57     ": <aeroplane> ( max-speed max-altitude -- aeroplane )"
58     "    aeroplane new"
59     "        V{ } clone >>occupants"
60     "        swap >>max-altitude"
61     "        swap >>max-speed ;"
62 }
63 "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:"
64 { $code
65     "TUPLE: vehicle max-speed occupants ;"
66     ""
67     ": add-occupant ( person vehicle -- ) occupants>> push ;"
68     ""
69     ": new-vehicle ( class -- vehicle )"
70     "    new"
71     "        V{ } clone >>occupants ;"
72     ""
73     "TUPLE: car < vehicle engine ;"
74     ": <car> ( max-speed engine -- car )"
75     "    car new-vehicle"
76     "        swap >>engine"
77     "        swap >>max-speed ;"
78     ""
79     "TUPLE: aeroplane < vehicle max-altitude ;"
80     ": <aeroplane> ( max-speed max-altitude -- aeroplane )"
81     "    aeroplane new-vehicle"
82     "        swap >>max-altitude"
83     "        swap >>max-speed ;"
84 }
85 "The naming convention for parametrized constructors is " { $snippet "new-" { $emphasis "class" } } "." ;
86
87 ARTICLE: "tuple-constructors" "Tuple constructors"
88 "Tuples are created by calling one of two constructor primitives:"
89 { $subsections
90     new
91     boa
92 }
93 "A shortcut for defining BOA constructors:"
94 { $subsections POSTPONE: C: }
95 "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>" } "."
96 $nl
97 "Constructors play a part in enforcing the invariant that slot values must always match slot declarations. The " { $link new } " word fills in the tuple with initial values, and " { $link boa } " ensures that the values on the stack match the corresponding slot declarations. See " { $link "tuple-declarations" } "."
98 $nl
99 "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 construct a different class, without breaking callers."
100 $nl
101 "Examples of constructors:"
102 { $code
103     "TUPLE: color"
104     "{ red integer }"
105     "{ green integer }"
106     "{ blue integer }"
107     "{ alpha integer initial: 1 } ;"
108     ""
109     "! The following two are equivalent"
110     "C: <rgba> color"
111     ": <rgba> color boa ;"
112     ""
113     "! We can define constructors which call other constructors"
114     ": <rgb> ( r g b -- color ) 1 <rgba> ;"
115     ""
116     "! The following two are equivalent; note the initial value"
117     ": <color> ( -- color ) color new ;"
118     ": <color> ( -- color ) 0 0 0 1 <rgba> ;"
119     "! Run-time error"
120     "\"not a number\" 2 3 4 color boa"
121 }
122 { $subsections "parametrized-constructors" } ;
123
124 ARTICLE: "tuple-inheritance-example" "Tuple subclassing example"
125 "Rectangles, parallelograms and circles are all shapes. We support two operations on shapes:"
126 { $list
127     "Computing the area"
128     "Computing the perimiter"
129 }
130 "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:"
131 { $code
132     "USING: accessors kernel math math.constants math.functions ;"
133     "GENERIC: area ( shape -- n )"
134     "GENERIC: perimiter ( shape -- n )"
135     ""
136     "TUPLE: shape ;"
137     ""
138     "TUPLE: circle < shape radius ;"
139     "M: circle area radius>> sq pi * ;"
140     "M: circle perimiter radius>> 2 * pi * ;"
141     ""
142     "TUPLE: quad < shape width height ;"
143     "M: quad area [ width>> ] [ height>> ] bi * ;"
144     ""
145     "TUPLE: rectangle < quad ;"
146     "M: rectangle perimiter [ width>> 2 * ] [ height>> 2 * ] bi + ;"
147     ""
148     ": hypot ( a b -- c ) [ sq ] bi@ + sqrt ;"
149     ""
150     "TUPLE: parallelogram < quad skew ;"
151     "M: parallelogram perimiter"
152     "    [ width>> 2 * ] [ [ height>> ] [ skew>> ] bi hypot 2 * ] bi + ;"
153 } ;
154
155 ARTICLE: "tuple-inheritance-anti-example" "When not to use tuple subclassing"
156 "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."
157 { $heading "Anti-pattern #1: subclassing for has-a" }
158 "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."
159 $nl
160 "For example, suppose that " { $snippet "shape" } " inherits from " { $snippet "color" } ":"
161 { $code
162     "TUPLE: color r g b ;"
163     "TUPLE: shape < color ... ;"
164 }
165 "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:"
166 { $code
167     "TUPLE: rgb-color r g b ;"
168     "TUPLE: hsv-color h s v ;"
169     "..."
170     "TUPLE: shape color ... ;"
171 }
172 "The " { $vocab-link "delegate" } " library provides a language abstraction for expressing has-a relationships."
173 { $heading "Anti-pattern #2: subclassing for implementation sharing only" }
174 "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 property does not hold, then subclassing should not be used."
175 $nl
176 "There are two alternatives which are preferred to subclassing in this case. The first is " { $link "mixins" } "."
177 $nl
178 "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."
179 { $heading "Anti-pattern #3: subclassing to override a method definition" }
180 "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 what subclasses may and may not do. This includes construction policy; document whether subclasses should use " { $link new } ", " { $link boa } ", or a custom parametrized constructor."
181 { $see-also "parametrized-constructors" } ;
182
183 ARTICLE: "tuple-subclassing" "Tuple subclassing"
184 "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" } "."
185 $nl
186 "To define one tuple class as a subclass of another, use the optional superclass parameter to " { $link POSTPONE: TUPLE: } ":"
187 { $code
188     "TUPLE: subclass < superclass ... ;"
189 }
190 { $subsections
191     "tuple-inheritance-example"
192     "tuple-inheritance-anti-example"
193
194 "Declaring a tuple class final prohibits other classes from subclassing it:"
195 { $subsections POSTPONE: final }
196 { $see-also "call-next-method" "parametrized-constructors" "unions" "mixins" } ;
197
198 ARTICLE: "tuple-introspection" "Tuple introspection"
199 "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."
200 { $subsections
201     >tuple
202     tuple>array
203     tuple-slots
204 }
205 "Tuples can be compared for slot equality even if the tuple class overrides " { $link equal? } ":"
206 { $subsections tuple= }
207 "Tuple classes can also be defined at run time:"
208 { $subsections define-tuple-class }
209 { $see-also "slots" "mirrors" } ;
210
211 ARTICLE: "tuple-examples" "Tuple examples"
212 "An example:"
213 { $code "TUPLE: employee name position salary ;" }
214 "This defines a class word named " { $snippet "employee" } ", a predicate " { $snippet "employee?" } ", and the following slot accessors:"
215 { $table
216     { "Reader" "Writer" "Setter" "Changer" }
217     { { $snippet "name>>" } { $snippet "name<<" } { $snippet ">>name" } { $snippet "change-name" } }
218     { { $snippet "salary>>" } { $snippet "salary<<" } { $snippet ">>salary" } { $snippet "change-salary" } }
219     { { $snippet "position>>" } { $snippet "position<<" } { $snippet ">>position" } { $snippet "change-position" }   }
220 }
221 "We can define a constructor which makes an empty employee:"
222 { $code ": <employee> ( -- employee )"
223     "    employee new ;" }
224 "Or we may wish the default constructor to always give employees a starting salary:"
225 { $code
226     ": <employee> ( -- employee )"
227     "    employee new"
228     "        40000 >>salary ;"
229 }
230 "We can define more refined constructors:"
231 { $code
232     ": <manager> ( -- manager )"
233     "    <employee> \"project manager\" >>position ;" }
234 "An alternative strategy is to define the most general BOA constructor first:"
235 { $code
236     ": <employee> ( name position -- employee )"
237     "    40000 employee boa ;"
238 }
239 "Now we can define more specific constructors:"
240 { $code
241     ": <manager> ( name -- employee )"
242     "    \"manager\" <employee> ;" }
243 "An example using reader words:"
244 { $code
245     "TUPLE: check to amount number ;"
246     ""
247     "SYMBOL: checks"
248     ""
249     ": <check> ( to amount -- check )"
250     "    checks counter check boa ;"
251     ""
252     ": biweekly-paycheck ( employee -- check )"
253     "    [ name>> ] [ salary>> 26 / ] bi <check> ;"
254 }
255 "An example of using a changer:"
256 { $code
257     ": positions ( -- seq )"
258     "    {"
259     "        \"junior programmer\""
260     "        \"senior programmer\""
261     "        \"project manager\""
262     "        \"department manager\""
263     "        \"executive\""
264     "        \"CTO\""
265     "        \"CEO\""
266     "        \"enterprise Java world dictator\""
267     "    } ;"
268     ""
269     ": next-position ( role -- newrole )"
270     "    positions [ index 1 + ] keep nth ;"
271     ""
272     ": promote ( employee -- employee )"
273     "    [ 1.2 * ] change-salary"
274     "    [ next-position ] change-position ;"
275 }
276 "An example using subclassing can be found in " { $link "tuple-inheritance-example" } "." ;
277
278 ARTICLE: "tuple-redefinition" "Tuple redefinition"
279 "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."
280 $nl
281 "When the " { $emphasis "effective slots" } " of a tuple class change, all instances of the class, including subclasses, are updated."
282 $nl
283 "There are three ways in which the list of effective slots may change:"
284 { $list
285     "Adding or removing direct slots of the class"
286     "Adding or removing direct slots of a superclass of the class"
287     "Changing the inheritance hierarchy by changing the superclass of a class"
288     "Declarations changing on existing slots"
289 }
290 "In all cases, the new effective slots are compared with the old effective slots, and each instance is updated as follows:"
291 { $list
292     "If any slots were removed, the values are removed from the instance and are lost forever."
293     "If any slots were added, the instance gains these slots, all set to their initial values."
294     "If any slots are permuted, their values in instances do not change; only the layout of the instance changes in memory."
295     "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."
296     "If the number or order of effective slots changes, any BOA constructors are recompiled."
297 }
298 "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." ;
299
300 ARTICLE: "protocol-slots" "Protocol slots"
301 "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."
302 $nl
303 "Protocol slots are defined using a parsing word:"
304 { $subsections POSTPONE: SLOT: }
305 "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."
306 $nl
307 "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: " { $snippet "SLOT: length" } " and " { $snippet "SLOT: underlying" } ". "
308 "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."
309 $nl
310 "For example, compare the definitions of the " { $link sbuf } " class,"
311 { $code
312     "TUPLE: sbuf"
313     "{ underlying string }"
314     "{ length array-capacity } ;"
315     ""
316     "INSTANCE: sbuf growable"
317 }
318 "with that of the " { $link vector } " class:"
319 { $code
320     "TUPLE: vector"
321     "{ underlying array }"
322     "{ length array-capacity } ;"
323     ""
324     "INSTANCE: vector growable"
325 } ;
326
327 ARTICLE: "tuples" "Tuples"
328 "Tuples are user-defined classes composed of named slots. They are the central data type of Factor's object system."
329 { $subsections "tuple-examples" }
330 "A parsing word defines tuple classes:"
331 { $subsections POSTPONE: TUPLE: }
332 "For each tuple class, several words are defined, the class word, a class predicate, and accessor words for each slot."
333 $nl
334 "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."
335 { $subsections
336     "accessors"
337     "tuple-constructors"
338     "tuple-subclassing"
339     "tuple-declarations"
340     "protocol-slots"
341     "tuple-introspection"
342 }
343 "Tuple classes can be redefined; this updates existing instances:"
344 { $subsections "tuple-redefinition" }
345 "Tuple literal syntax is documented in " { $link "syntax-tuples" } "." ;
346
347 ABOUT: "tuples"
348
349 HELP: tuple-class
350 { $class-description "The class of tuple class words." }
351 { $examples { $example "USING: classes.tuple prettyprint ;" "IN: scratchpad" "TUPLE: name title first last ;" "name tuple-class? ." "t" } } ;
352
353 HELP: tuple=
354 { $values { "tuple1" tuple } { "tuple2" tuple } { "?" "a boolean" } }
355 { $description "Checks if two tuples have equal slot values. This is the default behavior of " { $link = } " on tuples, unless the tuple class subclasses " { $link identity-tuple } " or implements a method on " { $link equal? } ". In cases where equality has been redefined, this word can be used to get the default semantics if needed." } ;
356
357 HELP: tuple
358 { $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."
359 $nl
360 "Tuple classes have additional word properties:"
361 { $list
362     { { $snippet "\"predicate\"" } " - a quotation which tests if the top of the stack is an instance of this tuple class" }
363     { { $snippet "\"slots\"" } " - a sequence of " { $link slot-spec } " instances" }
364     { { $snippet "\"layout\"" } " - an array with the tuple size and superclasses encoded in a format amneable to fast method dispatch" }
365 } } ;
366
367 HELP: define-tuple-predicate
368 { $values { "class" tuple-class } }
369 { $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." }
370 $low-level-note ;
371
372 HELP: redefine-tuple-class
373 { $values { "class" class } { "superclass" class } { "slots" "a sequence of strings" } }
374 { $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."
375 $nl
376 "If the class is not a tuple class word, this word does nothing." }
377 $low-level-note ;
378
379 HELP: tuple-slots
380 { $values { "tuple" tuple } { "seq" sequence } }
381 { $description "Pushes a sequence of tuple slot values, not including the tuple class word." } ;
382
383 { tuple-slots tuple>array } related-words
384
385 HELP: define-tuple-slots
386 { $values { "class" tuple-class } }
387 { $description "Defines slot accessor and mutator words for the tuple." }
388 $low-level-note ;
389
390 HELP: check-tuple
391 { $values { "class" class } }
392 { $description "Throws a " { $link check-tuple } " error if " { $snippet "word" } " is not a tuple class word." }
393 { $error-description "Thrown if " { $link POSTPONE: C: } " is called with a word which does not name a tuple class." } ;
394
395 HELP: define-tuple-class
396 { $values { "class" word } { "superclass" class } { "slots" "a sequence of strings" } }
397 { $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: } "." }
398 { $notes "This word must be called from inside " { $link with-compilation-unit } "." }
399 { $side-effects "class" } ;
400
401 { tuple-class define-tuple-class POSTPONE: TUPLE: } related-words
402
403 HELP: >tuple
404 { $values { "seq" sequence } { "tuple" tuple } }
405 { $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."
406 $nl
407 "If the sequence has too few elements, the remaining slots in the tuple are set to their initial values." }
408 { $errors "Throws an error if one of the following occurs:"
409     { $list
410         "the first element of the sequence is not a tuple class word"
411         "the values in the sequence do not satisfy the slot class predicates"
412         "the sequence is too long"
413     }
414 } ;
415
416 HELP: tuple>array ( tuple -- array )
417 { $values { "tuple" tuple } { "array" array } }
418 { $description "Outputs an array having the tuple's slots as elements. The first element is the tuple class word and remainder are declared slots." } ;
419
420 HELP: <tuple> ( layout -- tuple )
421 { $values { "layout" "a tuple layout array" } { "tuple" tuple } }
422 { $description "Low-level tuple constructor. User code should never call this directly, and instead use " { $link new } "." } ;
423
424 HELP: <tuple-boa> ( slots... layout -- tuple )
425 { $values { "slots..." "values" } { "layout" "a tuple layout array" } { "tuple" tuple } }
426 { $description "Low-level tuple constructor. User code should never call this directly, and instead use " { $link boa } "." } ;
427
428 HELP: new
429 { $values { "class" tuple-class } { "tuple" tuple } }
430 { $description "Creates a new instance of " { $snippet "class" } " with all slots set to their initial values (see " { $link "tuple-declarations" } ")." }
431 { $examples
432     { $example
433         "USING: kernel prettyprint ;"
434         "IN: scratchpad"
435         "TUPLE: employee number name department ;"
436         "employee new ."
437         "T{ employee }"
438     }
439 } ;
440
441 HELP: boa
442 { $values { "slots..." "slot values" } { "class" tuple-class } { "tuple" tuple } }
443 { $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." }
444 { $notes "The name " { $snippet "boa" } " is shorthand for “by order of arguments”, and “BOA constructor” is a pun on “boa constrictor”." }
445 { $errors "Throws an error if the slot values do not match class declarations on slots (see" { $link "tuple-declarations" } ")." } ;
446
447 HELP: bad-superclass
448 { $error-description "Thrown if an attempt is made to subclass a class that is not a tuple class, or a tuple class declared " { $link POSTPONE: final } "." } ;