PageRenderTime 66ms CodeModel.GetById 14ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/core/classes/tuple/tuple-docs.factor

http://github.com/abeaumont/factor
Unknown | 470 lines | 432 code | 38 blank | 0 comment | 0 complexity | ff6c1ebbcdcfe5bc0dc7aa73cc7f7cd0 MD5 | raw file
  1USING: generic help.markup help.syntax kernel
  2classes.tuple.private classes slots quotations words arrays
  3generic.standard sequences definitions compiler.units
  4growable vectors sbufs assocs math strings ;
  5IN: classes.tuple
  6
  7ARTICLE: "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
 10ARTICLE: "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
 22ARTICLE: "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
 27ARTICLE: "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
 40ARTICLE: "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
 87ARTICLE: "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
124ARTICLE: "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 perimeter"
129}
130"Rectangles and parallelograms use the same algorithm for computing the area, whereas they use different algorithms for computing perimeter. 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: perimeter ( shape -- n )"
135    ""
136    "TUPLE: shape ;"
137    ""
138    "TUPLE: circle < shape radius ;"
139    "M: circle area radius>> sq pi * ;"
140    "M: circle perimeter 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 perimeter [ width>> 2 * ] [ height>> 2 * ] bi + ;"
147    ""
148    ": hypot ( a b -- c ) [ sq ] bi@ + sqrt ;"
149    ""
150    "TUPLE: parallelogram < quad skew ;"
151    "M: parallelogram perimeter"
152    "    [ width>> 2 * ] [ [ height>> ] [ skew>> ] bi hypot 2 * ] bi + ;"
153} ;
154
155ARTICLE: "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 contrived 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
183ARTICLE: "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
198ARTICLE: "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
211ARTICLE: "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 "position>>" } { $snippet "position<<" } { $snippet ">>position" } { $snippet "change-position" } }
219    { { $snippet "salary>>" } { $snippet "salary<<" } { $snippet ">>salary" } { $snippet "change-salary" } }
220}
221"We can define a constructor which makes an empty employee:"
222{ $code
223    ": <employee> ( -- employee )"
224    "    employee new ;"
225}
226"Or we may wish the default constructor to always give employees a starting salary:"
227{ $code
228    ": <employee> ( -- employee )"
229    "    employee new"
230    "        40000 >>salary ;"
231}
232"We can define more refined constructors:"
233{ $code
234    ": <manager> ( -- manager )"
235    "    <employee> \"project manager\" >>position ;" }
236"An alternative strategy is to define the most general BOA constructor first:"
237{ $code
238    ": <employee> ( name position -- employee )"
239    "    40000 employee boa ;"
240}
241"Now we can define more specific constructors:"
242{ $code
243    ": <manager> ( name -- employee )"
244    "    \"manager\" <employee> ;" }
245"An example using reader words:"
246{ $code
247    "TUPLE: check to amount number ;"
248    ""
249    "SYMBOL: checks"
250    ""
251    ": <check> ( to amount -- check )"
252    "    checks counter check boa ;"
253    ""
254    ": biweekly-paycheck ( employee -- check )"
255    "    [ name>> ] [ salary>> 26 / ] bi <check> ;"
256}
257"An example of using a changer:"
258{ $code
259    ": positions ( -- seq )"
260    "    {"
261    "        \"junior programmer\""
262    "        \"senior programmer\""
263    "        \"project manager\""
264    "        \"department manager\""
265    "        \"executive\""
266    "        \"CTO\""
267    "        \"CEO\""
268    "        \"enterprise Java world dictator\""
269    "    } ;"
270    ""
271    ": next-position ( role -- newrole )"
272    "    positions [ index 1 + ] keep nth ;"
273    ""
274    ": promote ( employee -- employee )"
275    "    [ 1.2 * ] change-salary"
276    "    [ next-position ] change-position ;"
277}
278"An example using subclassing can be found in " { $link "tuple-inheritance-example" } "." ;
279
280ARTICLE: "tuple-redefinition" "Tuple redefinition"
281"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."
282$nl
283"When the " { $emphasis "effective slots" } " of a tuple class change, all instances of the class, including subclasses, are updated."
284$nl
285"There are three ways in which the list of effective slots may change:"
286{ $list
287    "Adding or removing direct slots of the class"
288    "Adding or removing direct slots of a superclass of the class"
289    "Changing the inheritance hierarchy by changing the superclass of a class"
290    "Declarations changing on existing slots"
291}
292"In all cases, the new effective slots are compared with the old effective slots, and each instance is updated as follows:"
293{ $list
294    "If any slots were removed, the values are removed from the instance and are lost forever."
295    "If any slots were added, the instance gains these slots, all set to their initial values."
296    "If any slots are permuted, their values in instances do not change; only the layout of the instance changes in memory."
297    "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."
298    "If the number or order of effective slots changes, any BOA constructors are recompiled."
299}
300"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." ;
301
302ARTICLE: "protocol-slots" "Protocol slots"
303"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."
304$nl
305"Protocol slots are defined using a parsing word:"
306{ $subsections POSTPONE: SLOT: }
307"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."
308$nl
309"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" } ". "
310"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."
311$nl
312"For example, compare the definitions of the " { $link sbuf } " class,"
313{ $code
314    "TUPLE: sbuf"
315    "{ underlying string }"
316    "{ length array-capacity } ;"
317    ""
318    "INSTANCE: sbuf growable"
319}
320"with that of the " { $link vector } " class:"
321{ $code
322    "TUPLE: vector"
323    "{ underlying array }"
324    "{ length array-capacity } ;"
325    ""
326    "INSTANCE: vector growable"
327} ;
328
329ARTICLE: "tuples" "Tuples"
330"Tuples are user-defined classes composed of named slots. They are the central data type of Factor's object system."
331{ $subsections "tuple-examples" }
332"A parsing word defines tuple classes:"
333{ $subsections POSTPONE: TUPLE: }
334"For each tuple class, several words are defined, the class word, a class predicate, and accessor words for each slot."
335$nl
336"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."
337{ $subsections
338    "accessors"
339    "tuple-constructors"
340    "tuple-subclassing"
341    "tuple-declarations"
342    "protocol-slots"
343    "tuple-introspection"
344}
345"Tuple classes can be redefined; this updates existing instances:"
346{ $subsections "tuple-redefinition" }
347"Tuple literal syntax is documented in " { $link "syntax-tuples" } "." ;
348
349ABOUT: "tuples"
350
351HELP: tuple-class
352{ $class-description "The class of tuple class words." }
353{ $examples { $example "USING: classes.tuple prettyprint ;" "IN: scratchpad" "TUPLE: name title first last ;" "name tuple-class? ." "t" } } ;
354
355HELP: tuple=
356{ $values { "tuple1" tuple } { "tuple2" tuple } { "?" "a boolean" } }
357{ $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." } ;
358
359HELP: tuple
360{ $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."
361$nl
362"Tuple classes have additional word properties:"
363{ $list
364    { { $snippet "\"predicate\"" } " - a quotation which tests if the top of the stack is an instance of this tuple class" }
365    { { $snippet "\"slots\"" } " - a sequence of " { $link slot-spec } " instances" }
366    { { $snippet "\"layout\"" } " - an array with the tuple size and superclasses encoded in a format amneable to fast method dispatch" }
367} } ;
368
369HELP: define-tuple-predicate
370{ $values { "class" tuple-class } }
371{ $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." }
372$low-level-note ;
373
374HELP: redefine-tuple-class
375{ $values { "class" class } { "superclass" class } { "slots" "a sequence of strings" } }
376{ $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."
377$nl
378"If the class is not a tuple class word, this word does nothing." }
379$low-level-note ;
380
381HELP: tuple-slots
382{ $values { "tuple" tuple } { "seq" sequence } }
383{ $description "Pushes a sequence of tuple slot values, not including the tuple class word." } ;
384
385{ tuple-slots tuple>array } related-words
386
387HELP: define-tuple-slots
388{ $values { "class" tuple-class } }
389{ $description "Defines slot accessor and mutator words for the tuple." }
390$low-level-note ;
391
392HELP: check-tuple
393{ $values { "class" class } }
394{ $description "Throws a " { $link check-tuple } " error if " { $snippet "word" } " is not a tuple class word." }
395{ $error-description "Thrown if " { $link POSTPONE: C: } " is called with a word which does not name a tuple class." } ;
396
397HELP: define-tuple-class
398{ $values { "class" word } { "superclass" class } { "slots" "a sequence of strings" } }
399{ $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: } "." }
400{ $notes "This word must be called from inside " { $link with-compilation-unit } "." }
401{ $side-effects "class" } ;
402
403{ tuple-class define-tuple-class POSTPONE: TUPLE: } related-words
404
405HELP: >tuple
406{ $values { "seq" sequence } { "tuple" tuple } }
407{ $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."
408$nl
409"If the sequence has too few elements, the remaining slots in the tuple are set to their initial values." }
410{ $errors "Throws an error if one of the following occurs:"
411    { $list
412        "the first element of the sequence is not a tuple class word"
413        "the values in the sequence do not satisfy the slot class predicates"
414        "the sequence is too long"
415    }
416} ;
417
418HELP: tuple>array
419{ $values { "tuple" tuple } { "array" array } }
420{ $description "Outputs an array having the tuple's slots as elements. The first element is the tuple class word and remainder are declared slots." } ;
421
422HELP: <tuple>
423{ $values { "layout" "a tuple layout array" } { "tuple" tuple } }
424{ $description "Low-level tuple constructor. User code should never call this directly, and instead use " { $link new } "." } ;
425
426HELP: <tuple-boa>
427{ $values { "slots..." "values" } { "layout" "a tuple layout array" } { "tuple" tuple } }
428{ $description "Low-level tuple constructor. User code should never call this directly, and instead use " { $link boa } "." } ;
429
430HELP: new
431{ $values { "class" tuple-class } { "tuple" tuple } }
432{ $description "Creates a new instance of " { $snippet "class" } " with all slots set to their initial values (see " { $link "tuple-declarations" } ")." }
433{ $examples
434    { $example
435        "USING: kernel prettyprint ;"
436        "IN: scratchpad"
437        "TUPLE: employee number name department ;"
438        "employee new ."
439        "T{ employee }"
440    }
441} ;
442
443HELP: boa
444{ $values { "slots..." "slot values" } { "class" tuple-class } { "tuple" tuple } }
445{ $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." }
446{ $notes "The name " { $snippet "boa" } " is shorthand for “by order of arguments”, and “BOA constructor” is a pun on “boa constrictor”." }
447{ $errors "Throws an error if the slot values do not match class declarations on slots (see " { $link "tuple-declarations" } ")." } ;
448
449HELP: bad-superclass
450{ $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 } "." } ;
451
452HELP: offset-of-slot
453{ $values { "name" string } { "tuple" tuple } { "n" integer } }
454{ $description "Returns the offset of a tuple slot accessed by " { $snippet "name" } "." } ;
455
456HELP: get-slot-named
457{ $values { "name" string } { "tuple" tuple } { "value" object } }
458{ $description "Returns the " { $snippet "value" } " stored in a tuple slot accessed by " { $snippet "name" } "." } ;
459
460HELP: set-slot-named
461{ $values { "value" object } { "name" string } { "tuple" tuple } }
462{ $description "Stores the " { $snippet "value" } " into a tuple slot accessed by " { $snippet "name" } "." } ;
463
464HELP: set-slots
465{ $values { "assoc" assoc } { "tuple" tuple } }
466{ $description "For each " { $snippet "{ key value }" } " pair in " { $snippet "assoc" } ", sets the " { $snippet "key" } " slot in " { $snippet "obj" } " to " { $snippet "value" } "." } ;
467
468HELP: from-slots
469{ $values { "assoc" assoc } { "class" tuple-class } { "tuple" tuple } }
470{ $description "Creates a new instance of " { $snippet "class" } " with slot values specified by " { $snippet "assoc" } "." } ;