]> gitweb.factorcode.org Git - factor.git/blob - core/slots/slots-docs.factor
mason: show git SHA1 and timestamp of last completed build
[factor.git] / core / slots / slots-docs.factor
1 USING: help.markup help.syntax
2 kernel quotations sequences
3 generic.standard classes.builtin slots.private classes strings math
4 assocs byte-arrays alien classes.tuple ;
5 IN: slots
6
7 ARTICLE: "accessors" "Slot accessors"
8 "For every tuple slot, a " { $emphasis "reader" } " method is defined in the " { $vocab-link "accessors" } " vocabulary. The reader is named " { $snippet "slot>>" } " and given a tuple, pushes the slot value on the stack."
9 $nl
10 "Writable slots —- that is, those not attributed " { $link read-only } " —- also have a " { $emphasis "writer" } ". The writer is named " { $snippet "slot<<" } " and stores a value into a slot. It has stack effect " { $snippet "( value object -- )" } ". If the slot is specialized to a specific class, the writer checks that the value being written into the slot is an instance of that class first. See " { $link "tuple-declarations" } " for details."
11 $nl
12 "In addition, two utility words are defined for each writable slot."
13 $nl
14 "The " { $emphasis "setter" } " is named " { $snippet ">>slot" } " and stores a value into a slot. It has stack effect " { $snippet "( object value -- object )" } "."
15 $nl
16 "The " { $emphasis "changer" } " is named " { $snippet "change-slot" } ". It applies a quotation to the current slot value and stores the result back in the slot; it has stack effect " { $snippet "( object quot -- object )" } "."
17 $nl
18 "Since the reader and writer are generic, words can be written which do not depend on the specific class of tuple passed in, but instead work on any tuple that defines slots with certain names."
19 $nl
20 "In most cases, using the setter is preferred over the writer because the stack effect is better suited to the common case where the tuple is needed again, and where the new slot value was just computed and so is at the top of the stack. For example, consider the case where you want to create a tuple and fill in the slots with literals. The following version uses setters:"
21 { $code
22     "<email>"
23     "    \"Happy birthday\" >>subject"
24     "    { \"bob@bigcorp.com\" } >>to"
25     "    \"alice@bigcorp.com\" >>from"
26     "send-email"
27 }
28 "The following uses writers, and requires some stack shuffling:"
29 { $code
30     "<email>"
31     "    \"Happy birthday\" over subject<<"
32     "    { \"bob@bigcorp.com\" } over to<<"
33     "    \"alice@bigcorp.com\" over from<<"
34     "send-email"
35 }
36 "Even if some of the slot values come from the stack underneath the tuple being constructed, setters win:"
37 { $code
38     "<email>"
39     "    swap >>subject"
40     "    swap >>to"
41     "    \"alice@bigcorp.com\" >>from"
42     "send-email"
43 }
44 "The above has less shuffling than the writer version:"
45 { $code
46     "<email>"
47     "    [ subject<< ] keep"
48     "    [ to<< ] keep"
49     "    \"alice@bigcorp.com\" over from<<"
50     "send-email"
51 }
52 "The changer word abstracts a common pattern where a slot value is read then stored again; so the following is not idiomatic code:"
53 { $code
54     "find-manager"
55     "    salary>> 0.75 * >>salary"
56 }
57 "The following version is preferred:"
58 { $code
59     "find-manager"
60     "    [ 0.75 * ] change-salary"
61 }
62 { $see-also "slots" "mirrors" } ;
63
64 ARTICLE: "slot-initial-values" "Initial values of slots"
65 "An initial value for a slot can be specified with the " { $link initial: } " slot declaration attribute. For certain classes, the initial value is optional; in these cases, it does not need to be specified. For others, it is required. Initial values can be used independently of class declaration, but if specified, the value must satisfy the class predicate."
66 $nl
67 "The following classes have default initial values:"
68 { $table
69     { { { $link f } } { $link f } }
70     { { { $link fixnum } } { $snippet "0" } }
71     { { { $link float } } { $snippet "0.0" } }
72     { { { $link string } } { $snippet "\"\"" } }
73     { { { $link byte-array } } { $snippet "B{ }" } }
74     { { { $link pinned-alien } } { $snippet "BAD-ALIEN" } }
75 }
76 "All other classes are handled with one of two cases:"
77 { $list
78     { "If the class is a union or mixin class which " { $emphasis "contains" } " one of the above known classes, then the initial value of the class is that of the known class, with preference given to classes earlier in the list. For example, if the slot is declared " { $link object } " (this is the default), the initial value is " { $link f } ". Similarly for " { $link sequence } " and " { $link assoc } "." }
79     { "If the class is a tuple class, the initial value of the slot is a new, shared instance of the class created with " { $link new } "." }
80     { "Otherwise, a " { $link bad-initial-value } " error is thrown. In this case, an initial value must be specified explicitly using " { $link initial: } "." }
81 }
82 "A word can be used to check if a class has an initial value or not:"
83 { $subsections initial-value } ;
84
85 ARTICLE: "slots" "Low-level slot operations"
86 "The " { $vocab-link "slots" } " vocabulary contains words for introspecting the slots of an object. A " { $emphasis "slot" } " is a component of an object which can store a value."
87 $nl
88 { $link "tuples" } " are composed entirely of slots, and instances of " { $link "builtin-classes" } " consist of slots together with intrinsic data."
89 $nl
90 "The " { $snippet "\"slots\"" } " word property of built-in and tuple classes holds an array of " { $emphasis "slot specifiers" } " describing the slot layout of each instance."
91 { $subsections slot-spec }
92 "The four words associated with a slot can be looked up in the " { $vocab-link "accessors" } " vocabulary:"
93 { $subsections
94     reader-word
95     writer-word
96     setter-word
97     changer-word
98 }
99 "Looking up a slot by name:"
100 { $subsections slot-named }
101 "Defining slots dynamically:"
102 { $subsections
103     define-reader
104     define-writer
105     define-setter
106     define-changer
107     define-slot-methods
108     define-accessors
109 }
110 "Unsafe slot access:"
111 { $subsections
112     slot
113     set-slot
114 }
115 { $see-also "accessors" "mirrors" } ;
116
117 ABOUT: "slots"
118
119 HELP: bad-initial-value
120 { $error-description "Thrown by " { $link POSTPONE: TUPLE: } " if a slot has an impossible initial value."
121   { $examples
122     { $unchecked-example
123       "TUPLE: a { b integer initial: \"invalid\" } ;"
124       "1: TUPLE: a { b integer initial: \"invalid\" } ;"
125       "                                              ^"
126       "Incompatible initial value"
127       "name          \"b\""
128       "initial-value \"invalid\""
129       "class         integer"
130       ""
131       "Type :help for debugging help."
132     }
133   }
134 } ;
135
136 HELP: slot-spec
137 { $class-description "A slot specification. The " { $snippet "\"slots\"" } " word property of " { $link builtin-class } " and " { $link tuple-class } " instances holds sequences of slot specifications."
138 $nl
139 "The slots of a slot specification are:"
140 { $list
141     { { $snippet "name" } " - a " { $link string } " identifying the slot." }
142     { { $snippet "offset" } " - an " { $link integer } " offset specifying where the slot value is stored inside instances of the relevant class. This is an implementation detail." }
143     { { $snippet "class" } " - a " { $link class } " declaring the set of possible values for the slot." }
144     { { $snippet "initial" } " - an initial value for the slot." }
145     { { $snippet "read-only" } " - a boolean indicating whether the slot is read only or not. Read only slots do not have a writer method associated with them." }
146 } } ;
147
148 HELP: define-typecheck
149 { $values { "class" class } { "generic" "a generic word" } { "quot" quotation } { "props" "an assoc of word properties" } }
150 { $description
151     "Defines a generic word with the " { $link standard-combination } " using dispatch position 0, and having one method on " { $snippet "class" } "."
152     $nl
153     "This creates a definition analogous to the following code:"
154     { $code
155         "GENERIC: generic"
156         "M: class generic quot ;"
157     }
158     "It checks if the top of the stack is an instance of " { $snippet "class" } ", and if so, executes the quotation."
159 }
160 { $notes "This word is used internally to wrap unsafe low-level code in a type-checking stub." } ;
161
162 HELP: define-reader
163 { $values { "class" class } { "slot-spec" slot-spec } }
164 { $description "Defines a reader word to read a slot specified by " { $snippet "slot-spec" } "." }
165 $low-level-note ;
166
167 HELP: define-writer
168 { $values { "class" class } { "slot-spec" slot-spec } }
169 { $description "Defines a generic word " { $snippet "writer" } " to write a new value to a slot specified by " { $snippet "slot-spec" } "." }
170 $low-level-note ;
171
172 HELP: define-slot-methods
173 { $values { "class" class } { "slot-spec" slot-spec } }
174 { $description "Defines a reader, writer, setter and changer for a slot specified by " { $snippet "slot-spec" } "." }
175 $low-level-note ;
176
177 HELP: define-accessors
178 { $values { "class" class } { "specs" { $sequence slot-spec } } }
179 { $description "Defines slot methods." }
180 $low-level-note ;
181
182 HELP: slot
183 { $values { "obj" object } { "m" "a non-negative fixnum" } { "value" object } }
184 { $description "Reads the object stored at the " { $snippet "n" } "th slot of " { $snippet "obj" } "." }
185 { $warning "This word is in the " { $vocab-link "slots.private" } " vocabulary because it does not perform type or bounds checks, and slot numbers are implementation detail." } ;
186
187 HELP: set-slot
188 { $values { "value" object } { "obj" object } { "n" "a non-negative fixnum" } }
189 { $description "Writes " { $snippet "value" } " to the " { $snippet "n" } "th slot of " { $snippet "obj" } "." }
190 { $warning "This word is in the " { $vocab-link "slots.private" } " vocabulary because it does not perform type or bounds checks, and slot numbers are implementation detail." } ;
191
192 HELP: slot-named
193 { $values { "name" string } { "specs" { $sequence slot-spec } } { "spec/f" { $maybe slot-spec } } }
194 { $description "Outputs the " { $link slot-spec } " with the given name." } ;