]> gitweb.factorcode.org Git - factor.git/blob - core/kernel/kernel-docs.factor
fix a bunch of typos in docs
[factor.git] / core / kernel / kernel-docs.factor
1 USING: generic help.markup help.syntax math memory
2 namespaces sequences kernel.private layouts classes
3 vectors combinators quotations strings words
4 assocs arrays math.order ;
5 IN: kernel
6
7 HELP: eq? ( obj1 obj2 -- ? )
8 { $values { "obj1" object } { "obj2" object } { "?" "a boolean" } }
9 { $description "Tests if two references point at the same object." } ;
10
11 HELP: drop  ( x -- )                 $shuffle ;
12 HELP: 2drop ( x y -- )               $shuffle ;
13 HELP: 3drop ( x y z -- )             $shuffle ;
14 HELP: dup   ( x -- x x )             $shuffle ;
15 HELP: 2dup  ( x y -- x y x y )       $shuffle ;
16 HELP: 3dup  ( x y z -- x y z x y z ) $shuffle ;
17 HELP: rot   ( x y z -- y z x )       $shuffle ;
18 HELP: -rot  ( x y z -- z x y )       $shuffle ;
19 HELP: dupd  ( x y -- x x y )         $shuffle ;
20 HELP: swapd ( x y z -- y x z )       $shuffle ;
21 HELP: nip   ( x y -- y )             $shuffle ;
22 HELP: 2nip  ( x y z -- z )           $shuffle ;
23 HELP: tuck  ( x y -- y x y )         $shuffle ;
24 HELP: over  ( x y -- x y x )         $shuffle ;
25 HELP: 2over                          $shuffle ;
26 HELP: pick  ( x y z -- x y z x )     $shuffle ;
27 HELP: swap  ( x y -- y x )           $shuffle ;
28 HELP: spin                           $shuffle ;
29 HELP: roll                           $shuffle ;
30 HELP: -roll                          $shuffle ;
31
32 HELP: datastack ( -- ds )
33 { $values { "ds" array } }
34 { $description "Outputs an array containing a copy of the data stack contents right before the call to this word, with the top of the stack at the end of the array." } ;
35
36 HELP: set-datastack ( ds -- )
37 { $values { "ds" array } }
38 { $description "Replaces the data stack contents with a copy of an array. The end of the array becomes the top of the stack." } ;
39
40 HELP: retainstack ( -- rs )
41 { $values { "rs" array } }
42 { $description "Outputs an array containing a copy of the retain stack contents right before the call to this word, with the top of the stack at the end of the array." } ;
43
44 HELP: set-retainstack ( rs -- )
45 { $values { "rs" array } }
46 { $description "Replaces the retain stack contents with a copy of an array. The end of the array becomes the top of the stack." } ;
47
48 HELP: callstack ( -- cs )
49 { $values { "cs" callstack } }
50 { $description "Outputs a copy of the call stack contents, with the top of the stack at the end of the vector. The stack frame of the caller word is " { $emphasis "not" } " included." } ;
51
52 HELP: set-callstack ( cs -- )
53 { $values { "cs" callstack } }
54 { $description "Replaces the call stack contents. The end of the vector becomes the top of the stack. Control flow is transferred immediately to the new call stack." } ;
55
56 HELP: clear
57 { $description "Clears the data stack." } ;
58
59 HELP: build
60 { $values { "n" integer } }
61 { $description "The current build number. Factor increments this number whenever a new boot image is created." } ;
62
63 HELP: hashcode*
64 { $values { "depth" integer } { "obj" object } { "code" fixnum } }
65 { $contract "Outputs the hashcode of an object. The hashcode operation must satisfy the following properties:"
66 { $list
67     { "If two objects are equal under " { $link = } ", they must have equal hashcodes." }
68     { "If the hashcode of an object depends on the values of its slots, the hashcode of the slots must be computed recursively by calling " { $link hashcode* } " with a " { $snippet "level" } " parameter decremented by one. This avoids excessive work while still computing well-distributed hashcodes. The " { $link recursive-hashcode } " combinator can help with implementing this logic," }
69     { "The hashcode should be a " { $link fixnum } ", however returning a " { $link bignum } " will not cause any problems other than potential performance degradation." }
70     { "The hashcode is only permitted to change between two invocations if the object or one of its slot values was mutated." }
71 }
72 "If mutable objects are used as hashtable keys, they must not be mutated in such a way that their hashcode changes. Doing so will violate bucket sorting invariants and result in undefined behavior. See " { $link "hashtables.keys" } " for details." } ;
73
74 HELP: hashcode
75 { $values { "obj" object } { "code" fixnum } }
76 { $description "Computes the hashcode of an object with a default hashing depth. See " { $link hashcode* } " for the hashcode contract." } ;
77
78 { hashcode hashcode* } related-words
79
80 HELP: =
81 { $values { "obj1" object } { "obj2" object } { "?" "a boolean" } }
82 { $description
83     "Tests if two objects are equal. If " { $snippet "obj1" } " and " { $snippet "obj2" } " point to the same object, outputs " { $link t } ". Otherwise, calls the " { $link equal? } " generic word."
84 }
85 { $examples
86     { $example "USING: kernel prettyprint ;" "5 5 = ." "t" }
87     { $example "USING: kernel prettyprint ;" "5 005 = ." "t" }
88     { $example "USING: kernel prettyprint ;" "5 5.0 = ." "f" }
89     { $example "USING: arrays kernel prettyprint ;" "{ \"a\" \"b\" } \"a\" \"b\" 2array = ." "t" }
90     { $example "USING: arrays kernel prettyprint ;" "{ \"a\" \"b\" } [ \"a\" \"b\" ] = ." "f" }
91 } ;
92
93 HELP: equal?
94 { $values { "obj1" object } { "obj2" object } { "?" "a boolean" } }
95 { $contract
96     "Tests if two objects are equal."
97     $nl
98     "User code should call " { $link = } " instead; that word first tests the case where the objects are " { $link eq? } ", and so by extension, methods defined on " { $link equal? } " assume they are never called on " { $link eq? } " objects."
99     $nl
100     "Method definitions should ensure that this is an equality relation, modulo the assumption that the two objects are not " { $link eq? } ". That is, for any three non-" { $link eq? } " objects " { $snippet "a" } ", " { $snippet "b" } " and " { $snippet "c" } ", we must have:"
101     { $list
102         { { $snippet "a = b" } " implies " { $snippet "b = a" } }
103         { { $snippet "a = b" } " and " { $snippet "b = c" } " implies " { $snippet "a = c" } }
104     }
105     "If a class defines a custom equality comparison test, it should also define a compatible method for the " { $link hashcode* } " generic word."
106 }
107 { $examples
108     "An example demonstrating why this word should only be used to define methods on, and never called directly:"
109     { $example "USING: kernel prettyprint ;" "5 5 equal? ." "f" }
110     "Using " { $link = } " gives the expected behavior:"
111     { $example "USING: kernel prettyprint ;" "5 5 = ." "t" }
112 } ;
113
114 HELP: identity-tuple
115 { $class-description "A class defining an " { $link equal? } " method which always returns f." }
116 { $examples
117     "To define a tuple class such that two instances are only equal if they are both the same instance, inherit from the " { $link identity-tuple } " class. This class defines a method on " { $link equal? } " which always returns " { $link f } ". Since " { $link = } " handles the case where the two objects are " { $link eq? } ", this method will never be called with two " { $link eq? } " objects, so such a definition is valid:"
118     { $code "TUPLE: foo < identity-tuple ;" }
119     "By calling " { $link = } " on instances of " { $snippet "foo" } " we get the results we expect:"
120     { $unchecked-example "T{ foo } dup = ." "t" }
121     { $unchecked-example "T{ foo } dup clone = ." "f" }
122 } ;
123
124 HELP: clone
125 { $values { "obj" object } { "cloned" "a new object" } }
126 { $contract "Outputs a new object equal to the given object. This is not guaranteed to actually copy the object; it does nothing with immutable objects, and does not copy words either. However, sequences and tuples can be cloned to obtain a shallow copy of the original." } ;
127
128 HELP: ?
129 { $values { "?" "a generalized boolean" } { "true" object } { "false" object } { "true/false" "one two input objects" } }
130 { $description "Chooses between two values depending on the boolean value of " { $snippet "cond" } "." } ;
131
132 HELP: boolean
133 { $class-description "A union of the " { $link POSTPONE: t } " and " { $link POSTPONE: f } " classes." } ;
134
135 HELP: >boolean
136 { $values { "obj" "a generalized boolean" } { "?" "a boolean" } }
137 { $description "Convert a generalized boolean into a boolean. That is, " { $link f } " retains its value, whereas anything else becomes " { $link t } "." } ;
138
139 HELP: not
140 { $values { "obj" "a generalized boolean" } { "?" "a boolean" } }
141 { $description "For " { $link f } " outputs " { $link t } " and for anything else outputs " { $link f } "." }
142 { $notes "This word implements boolean not, so applying it to integers will not yield useful results (all integers have a true value). Bitwise not is the " { $link bitnot } " word." } ;
143
144 HELP: and
145 { $values { "obj1" "a generalized boolean" } { "obj2" "a generalized boolean" } { "?" "a generalized boolean" } }
146 { $description "If both inputs are true, outputs " { $snippet "obj2" } ". otherwise outputs " { $link f } "." }
147 { $notes "This word implements boolean and, so applying it to integers will not yield useful results (all integers have a true value). Bitwise and is the " { $link bitand } " word." }
148 { $examples
149     "Usually only the boolean value of the result is used, however you can also explicitly rely on the behavior that if both inputs are true, the second is output:"
150     { $example "USING: kernel prettyprint ;" "t f and ." "f" }
151     { $example "USING: kernel prettyprint ;" "t 7 and ." "7" }
152     { $example "USING: kernel prettyprint ;" "\"hi\" 12.0 and ." "12.0" }
153 } ;
154
155 HELP: or
156 { $values { "obj1" "a generalized boolean" } { "obj2" "a generalized boolean" } { "?" "a generalized boolean" } }
157 { $description "If both inputs are false, outputs " { $link f } ". otherwise outputs the first of " { $snippet "obj1" } " and " { $snippet "obj2" } " which is true." }
158 { $notes "This word implements boolean inclusive or, so applying it to integers will not yield useful results (all integers have a true value). Bitwise inclusive or is the " { $link bitor } " word." }
159 { $examples
160     "Usually only the boolean value of the result is used, however you can also explicitly rely on the behavior that the result will be the first true input:"
161     { $example "USING: kernel prettyprint ;" "t f or ." "t" }
162     { $example "USING: kernel prettyprint ;" "\"hi\" 12.0 or ." "\"hi\"" }
163 } ;
164
165 HELP: xor
166 { $values { "obj1" "a generalized boolean" } { "obj2" "a generalized boolean" } { "?" "a generalized boolean" } }
167 { $description "If exactly one input is false, outputs the other input. Otherwise outputs " { $link f } "." }
168 { $notes "This word implements boolean exclusive or, so applying it to integers will not yield useful results (all integers have a true value). Bitwise exclusive or is the " { $link bitxor } " word." } ;
169
170 HELP: both?
171 { $values { "x" object } { "y" object } { "quot" { $quotation "( obj -- ? )" } } { "?" "a boolean" } }
172 { $description "Tests if the quotation yields a true value when applied to both " { $snippet "x" } " and " { $snippet "y" } "." }
173 { $examples
174     { $example "USING: kernel math prettyprint ;" "3 5 [ odd? ] both? ." "t" }
175     { $example "USING: kernel math prettyprint ;" "12 7 [ even? ] both? ." "f" }
176 } ;
177
178 HELP: either?
179 { $values { "x" object } { "y" object } { "quot" { $quotation "( obj -- ? )" } } { "?" "a boolean" } }
180 { $description "Tests if the quotation yields a true value when applied to either " { $snippet "x" } " or " { $snippet "y" } "." }
181 { $examples
182     { $example "USING: kernel math prettyprint ;" "3 6 [ odd? ] either? ." "t" }
183     { $example "USING: kernel math prettyprint ;" "5 7 [ even? ] either? ." "f" }
184 } ;
185
186 HELP: execute
187 { $values { "word" word } }
188 { $description "Executes a word. Words which " { $link execute } " an input parameter must be declared " { $link POSTPONE: inline } " so that a caller which passes in a literal word can have a static stack effect." }
189 { $examples
190     { $example "USING: kernel io words ;" "IN: scratchpad" ": twice ( word -- ) dup execute execute ; inline\n: hello ( -- ) \"Hello\" print ;\n\\ hello twice" "Hello\nHello" }
191 } ;
192
193 { execute POSTPONE: execute( } related-words
194
195 HELP: (execute)
196 { $values { "word" word } }
197 { $description "Executes a word without checking if it is a word first." }
198 { $warning "This word is in the " { $vocab-link "kernel.private" } " vocabulary because it is unsafe. Calling with a parameter that is not a word will crash Factor. Use " { $link execute } " instead." } ;
199
200 HELP: call
201 { $values { "callable" callable } }
202 { $description "Calls a quotation. Words which " { $link call } " an input parameter must be declared " { $link POSTPONE: inline } " so that a caller which passes in a literal quotation can have a static stack effect." }
203 { $examples
204     "The following two lines are equivalent:"
205     { $code "2 [ 2 + 3 * ] call" "2 2 + 3 *" }
206 } ;
207
208 { call POSTPONE: call( } related-words
209
210 HELP: call-clear ( quot -- )
211 { $values { "quot" callable } }
212 { $description "Calls a quotation with an empty call stack. If the quotation returns, Factor will exit.." }
213 { $notes "Used to implement " { $link "threads" } "." } ;
214
215 HELP: keep
216 { $values { "x" object } { "quot" { $quotation "( x -- ... )" } } }
217 { $description "Call a quotation with a value on the stack, restoring the value when the quotation returns." }
218 { $examples
219     { $example "USING: arrays kernel prettyprint ;" "2 \"greetings\" [ <array> ] keep 2array ." "{ { \"greetings\" \"greetings\" } \"greetings\" }" }
220 } ;
221
222 HELP: 2keep
223 { $values { "x" object } { "y" object } { "quot" { $quotation "( x y -- ... )" } } }
224 { $description "Call a quotation with two values on the stack, restoring the values when the quotation returns." } ;
225
226 HELP: 3keep
227 { $values { "x" object } { "y" object } { "z" object } { "quot" { $quotation "( x y z -- ... )" } } }
228 { $description "Call a quotation with three values on the stack, restoring the values when the quotation returns." } ;
229
230 HELP: bi
231 { $values { "x" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( x -- ... )" } } }
232 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "x" } "." }
233 { $examples
234     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x -- )" } ", then the following two lines are equivalent:"
235     { $code
236         "[ p ] [ q ] bi"
237         "dup p q"
238     }
239     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x -- y )" } ", then the following two lines are equivalent:"
240     { $code
241         "[ p ] [ q ] bi"
242         "dup p swap q"
243     }
244     "In general, the following two lines are equivalent:"
245     { $code
246         "[ p ] [ q ] bi"
247         "[ p ] keep q"
248     }
249     
250 } ;
251
252 HELP: 2bi
253 { $values { "x" object } { "y" object } { "p" { $quotation "( x y -- ... )" } } { "q" { $quotation "( x y -- ... )" } } }
254 { $description "Applies " { $snippet "p" } " to the two input values, then applies " { $snippet "q" } " to the two input values." }
255 { $examples
256     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x y -- )" } ", then the following two lines are equivalent:"
257     { $code
258         "[ p ] [ q ] 2bi"
259         "2dup p q"
260     }
261     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x y -- z )" } ", then the following two lines are equivalent:"
262     { $code
263         "[ p ] [ q ] 2bi"
264         "2dup p -rot q"
265     }
266     "In general, the following two lines are equivalent:"
267     { $code
268         "[ p ] [ q ] 2bi"
269         "[ p ] 2keep q"
270     }
271 } ;
272
273 HELP: 3bi
274 { $values { "x" object } { "y" object } { "z" object } { "p" { $quotation "( x y z -- ... )" } } { "q" { $quotation "( x y z -- ... )" } } }
275 { $description "Applies " { $snippet "p" } " to the three input values, then applies " { $snippet "q" } " to the three input values." }
276 { $examples
277     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x y z -- )" } ", then the following two lines are equivalent:"
278     { $code
279         "[ p ] [ q ] 3bi"
280         "3dup p q"
281     }
282     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x y z -- w )" } ", then the following two lines are equivalent:"
283     { $code
284         "[ p ] [ q ] 3bi"
285         "3dup p -roll q"
286     }
287     "In general, the following two lines are equivalent:"
288     { $code
289         "[ p ] [ q ] 3bi"
290         "[ p ] 3keep q"
291     }
292 } ;
293
294 HELP: tri
295 { $values { "x" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( x -- ... )" } } { "r" { $quotation "( x -- ... )" } } }
296 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "x" } ", and finally applies " { $snippet "r" } " to " { $snippet "x" } "." }
297 { $examples
298     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x -- )" } ", then the following two lines are equivalent:"
299     { $code
300         "[ p ] [ q ] [ r ] tri"
301         "dup p dup q r"
302     }
303     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x -- y )" } ", then the following two lines are equivalent:"
304     { $code
305         "[ p ] [ q ] [ r ] tri"
306         "dup p over q rot r"
307     }
308     "In general, the following two lines are equivalent:"
309     { $code
310         "[ p ] [ q ] [ r ] tri"
311         "[ p ] keep [ q ] keep r"
312     }
313 } ;
314
315 HELP: 2tri
316 { $values { "x" object } { "y" object } { "p" { $quotation "( x y -- ... )" } } { "q" { $quotation "( x y -- ... )" } } { "r" { $quotation "( x y -- ... )" } } }
317 { $description "Applies " { $snippet "p" } " to the two input values, then applies " { $snippet "q" } " to the two input values, and finally applies " { $snippet "r" } " to the two input values." }
318 { $examples
319     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x y -- )" } ", then the following two lines are equivalent:"
320     { $code
321         "[ p ] [ q ] [ r ] 2tri"
322         "2dup p 2dup q r"
323     }
324     "In general, the following two lines are equivalent:"
325     { $code
326         "[ p ] [ q ] [ r ] 2tri"
327         "[ p ] 2keep [ q ] 2keep r"
328     }
329 } ;
330
331 HELP: 3tri
332 { $values { "x" object } { "y" object } { "z" object } { "p" { $quotation "( x y z -- ... )" } } { "q" { $quotation "( x y z -- ... )" } } { "r" { $quotation "( x y z -- ... )" } } }
333 { $description "Applies " { $snippet "p" } " to the three input values, then applies " { $snippet "q" } " to the three input values, and finally applies " { $snippet "r" } " to the three input values." }
334 { $examples
335     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x y z -- )" } ", then the following two lines are equivalent:"
336     { $code
337         "[ p ] [ q ] [ r ] 3tri"
338         "3dup p 3dup q r"
339     }
340     "In general, the following two lines are equivalent:"
341     { $code
342         "[ p ] [ q ] [ r ] 3tri"
343         "[ p ] 3keep [ q ] 3keep r"
344     }
345 } ;
346
347
348 HELP: bi*
349 { $values { "x" object } { "y" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( y -- ... )" } } }
350 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "y" } "." }
351 { $examples
352     "The following two lines are equivalent:"
353     { $code
354         "[ p ] [ q ] bi*"
355         "[ p ] dip q"
356     }
357 } ;
358
359 HELP: 2bi*
360 { $values { "w" object } { "x" object } { "y" object } { "z" object } { "p" { $quotation "( w x -- ... )" } } { "q" { $quotation "( y z -- ... )" } } }
361 { $description "Applies " { $snippet "p" } " to " { $snippet "w" } " and " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "y" } " and " { $snippet "z" } "." }
362 { $examples
363     "The following two lines are equivalent:"
364     { $code
365         "[ p ] [ q ] 2bi*"
366         "[ p ] 2dip q"
367     }
368 } ;
369
370 HELP: 2tri*
371 { $values { "u" object } { "v" object } { "w" object } { "x" object } { "y" object } { "z" object } { "p" { $quotation "( u v -- ... )" } } { "q" { $quotation "( w x -- ... )" } } { "r" { $quotation "( y z -- ... )" } } }
372 { $description "Applies " { $snippet "p" } " to " { $snippet "u" } " and " { $snippet "v" } ", then applies " { $snippet "q" } " to " { $snippet "w" } " and " { $snippet "x" } ", and finally applies " { $snippet "r" } " to " { $snippet "y" } " and " { $snippet "z" } "." }
373 { $examples
374     "The following two lines are equivalent:"
375     { $code
376         "[ p ] [ q ] [ r ] 2tri*"
377         "[ [ p ] 2dip q ] 2dip r"
378     }
379 } ;
380
381 HELP: tri*
382 { $values { "x" object } { "y" object } { "z" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( y -- ... )" } } { "r" { $quotation "( z -- ... )" } } }
383 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "y" } ", and finally applies " { $snippet "r" } " to " { $snippet "z" } "." }
384 { $examples
385     "The following two lines are equivalent:"
386     { $code
387         "[ p ] [ q ] [ r ] tri*"
388         "[ [ p ] dip q ] dip r"
389     }
390 } ;
391
392 HELP: bi@
393 { $values { "x" object } { "y" object } { "quot" { $quotation "( obj -- ... )" } } }
394 { $description "Applies the quotation to " { $snippet "x" } ", then to " { $snippet "y" } "." }
395 { $examples
396     "The following two lines are equivalent:"
397     { $code
398         "[ p ] bi@"
399         "[ p ] dip p"
400     }
401     "The following two lines are also equivalent:"
402     { $code
403         "[ p ] bi@"
404         "[ p ] [ p ] bi*"
405     }
406 } ;
407
408 HELP: 2bi@
409 { $values { "w" object } { "x" object } { "y" object } { "z" object } { "quot" { $quotation "( obj1 obj2 -- ... )" } } }
410 { $description "Applies the quotation to " { $snippet "w" } " and " { $snippet "x" } ", then to " { $snippet "y" } " and " { $snippet "z" } "." }
411 { $examples
412     "The following two lines are equivalent:"
413     { $code
414         "[ p ] 2bi@"
415         "[ p ] 2dip p"
416     }
417     "The following two lines are also equivalent:"
418     { $code
419         "[ p ] 2bi@"
420         "[ p ] [ p ] 2bi*"
421     }
422 } ;
423
424 HELP: tri@
425 { $values { "x" object } { "y" object } { "z" object } { "quot" { $quotation "( obj -- ... )" } } }
426 { $description "Applies the quotation to " { $snippet "x" } ", then to " { $snippet "y" } ", and finally to " { $snippet "z" } "." }
427 { $examples
428     "The following two lines are equivalent:"
429     { $code
430         "[ p ] tri@"
431         "[ [ p ] dip p ] dip p"
432     }
433     "The following two lines are also equivalent:"
434     { $code
435         "[ p ] tri@"
436         "[ p ] [ p ] [ p ] tri*"
437     }
438 } ;
439
440 HELP: 2tri@
441 { $values { "u" object } { "v" object } { "w" object } { "x" object } { "y" object } { "z" object } { "quot" { $quotation "( obj1 obj2 -- ... )" } } }
442 { $description "Applies the quotation to " { $snippet "u" } " and " { $snippet "v" } ", then to " { $snippet "w" } " and " { $snippet "x" } ", and then to " { $snippet "y" } " and " { $snippet "z" } "." }
443 { $examples
444     "The following two lines are equivalent:"
445     { $code
446         "[ p ] 2tri@"
447         "[ [ p ] 2dip p ] 2dip p"
448     }
449     "The following two lines are also equivalent:"
450     { $code
451         "[ p ] 2tri@"
452         "[ p ] [ p ] [ p ] 2tri*"
453     }
454 } ;
455
456 HELP: bi-curry
457 { $values { "x" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( x -- ... )" } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ x q ]" } } }
458 { $description "Partially applies " { $snippet "p" } " and " { $snippet "q" } " to " { $snippet "x" } "." }
459 { $notes
460   "The following two lines are equivalent:"
461   { $code
462     "[ p ] [ q ] bi-curry [ call ] bi@"
463     "[ p ] [ q ] bi"
464   }
465   "Higher-arity variants of " { $link bi } " can be built from " { $link bi-curry } ":"
466   { $code
467     "[ p ] [ q ] bi-curry bi == [ p ] [ q ] 2bi"
468     "[ p ] [ q ] bi-curry bi-curry bi == [ p ] [ q ] 3bi"
469   }
470   "The combination " { $snippet "bi-curry bi*" } " cannot be expressed with the non-currying dataflow combinators alone; it is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
471   { $code
472     "[ p ] [ q ] bi-curry bi*"
473     "[ swap ] keep [ p ] [ q ] 2bi*"
474   }
475   "To put it another way, " { $snippet "bi-curry bi*" } " handles the case where you have three values " { $snippet "a b c" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a c" } " and " { $snippet "q" } " to " { $snippet "b c" } "."
476 } ;
477
478 HELP: tri-curry
479 { $values
480   { "x" object }
481   { "p" { $quotation "( x -- ... )" } }
482   { "q" { $quotation "( x -- ... )" } }
483   { "r" { $quotation "( x -- ... )" } }
484   { "p'" { $snippet "[ x p ]" } }
485   { "q'" { $snippet "[ x q ]" } }
486   { "r'" { $snippet "[ x r ]" } }
487 }
488 { $description "Partially applies " { $snippet "p" } ", " { $snippet "q" } " and " { $snippet "r" } " to " { $snippet "x" } "." }
489 { $notes
490   "The following two lines are equivalent:"
491   { $code
492     "[ p ] [ q ] [ r ] tri-curry [ call ] tri@"
493     "[ p ] [ q ] [ r ] tri"
494   }
495   "Higher-arity variants of " { $link tri } " can be built from " { $link tri-curry } ":"
496   { $code
497     "[ p ] [ q ] [ r ] tri-curry tri == [ p ] [ q ] [ r ] 2tri"
498     "[ p ] [ q ] [ r ] tri-curry tri-curry bi == [ p ] [ q ] [ r ] 3tri"
499   }
500   "The combination " { $snippet "tri-curry tri*" } " cannot be expressed with the non-currying dataflow combinators alone; it handles the case where you have four values " { $snippet "a b c d" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a d" } ", " { $snippet "q" } " to " { $snippet "b d" } " and " { $snippet "r" } " to " { $snippet "c d" } "." } ;
501
502 HELP: bi-curry*
503 { $values { "x" object } { "y" object } { "p" { $quotation "( x -- ... )" } } { "q" { $quotation "( y -- ... )" } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ y q ]" } } }
504 { $description "Partially applies " { $snippet "p" } " to " { $snippet "x" } ", and " { $snippet "q" } " to " { $snippet "y" } "." }
505 { $notes
506   "The following two lines are equivalent:"
507   { $code
508     "[ p ] [ q ] bi-curry* [ call ] bi@"
509     "[ p ] [ q ] bi*"
510   }
511   "The combination " { $snippet "bi-curry* bi" } " is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
512   { $code
513     "[ p ] [ q ] bi-curry* bi"
514     "[ over ] dip [ p ] [ q ] 2bi*"
515   }
516   "In other words, " { $snippet "bi-curry* bi" } " handles the case where you have the three values " { $snippet "a b c" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a b" } " and " { $snippet "q" } " to " { $snippet "a c" } "."
517   $nl
518   "The combination " { $snippet "bi-curry* bi*" } " is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
519   { $code
520     "[ p ] [ q ] bi-curry* bi*"
521     "[ swap ] dip [ p ] [ q ] 2bi*"
522   }
523   "In other words, " { $snippet "bi-curry* bi*" } " handles the case where you have the four values " { $snippet "a b c d" } " on the stack, and you wish to apply " { $snippet "p" } " to " { $snippet "a c" } " and " { $snippet "q" } " to " { $snippet "b d" } "."
524   
525 } ;
526
527 HELP: tri-curry*
528 { $values
529   { "x" object }
530   { "y" object }
531   { "z" object }
532   { "p" { $quotation "( x -- ... )" } }
533   { "q" { $quotation "( y -- ... )" } }
534   { "r" { $quotation "( z -- ... )" } }
535   { "p'" { $snippet "[ x p ]" } }
536   { "q'" { $snippet "[ y q ]" } }
537   { "r'" { $snippet "[ z r ]" } }
538 }
539 { $description "Partially applies " { $snippet "p" } " to " { $snippet "x" } ", " { $snippet "q" } " to " { $snippet "y" } " and " { $snippet "r" } " to " { $snippet "z" } "." }
540 { $notes
541   "The following two lines are equivalent:"
542   { $code
543     "[ p ] [ q ] [ r ] tri-curry* [ call ] tri@"
544     "[ p ] [ q ] [ r ] tri*"
545   }
546   "The combination " { $snippet "tri-curry* tri" } " is equivalent to a stack shuffle preceding " { $link 2tri* } ":"
547   { $code
548     "[ p ] [ q ] [ r ] tri-curry* tri"
549     "[ [ over ] dip over ] dip [ p ] [ q ] [ r ] 2tri*"
550   }
551 } ;
552
553 HELP: bi-curry@
554 { $values { "x" object } { "y" object } { "q" { $quotation "( obj -- ... )" } } { "p'" { $snippet "[ x q ]" } } { "q'" { $snippet "[ y q ]" } } }
555 { $description "Partially applies " { $snippet "q" } " to " { $snippet "x" } " and " { $snippet "y" } "." }
556 { $notes
557   "The following two lines are equivalent:"
558   { $code
559     "[ q ] bi-curry@"
560     "[ q ] [ q ] bi-curry*"
561   }
562 } ;
563
564 HELP: tri-curry@
565 { $values
566   { "x" object }
567   { "y" object }
568   { "z" object }
569   { "q" { $quotation "( obj -- ... )" } }
570   { "p'" { $snippet "[ x q ]" } }
571   { "q'" { $snippet "[ y q ]" } }
572   { "r'" { $snippet "[ z q ]" } }
573 }
574 { $description "Partially applies " { $snippet "q" } " to " { $snippet "x" } ", " { $snippet "y" } " and " { $snippet "z" } "." }
575 { $notes
576   "The following two lines are equivalent:"
577   { $code
578     "[ q ] tri-curry@"
579     "[ q ] [ q ] [ q ] tri-curry*"
580   }
581 } ;
582
583 HELP: if
584 { $values { "?" "a generalized boolean" } { "true" quotation } { "false" quotation } }
585 { $description "If " { $snippet "cond" } " is " { $link f } ", calls the " { $snippet "false" } " quotation. Otherwise calls the " { $snippet "true" } " quotation."
586 $nl
587 "The " { $snippet "cond" } " value is removed from the stack before either quotation is called." } ;
588
589 HELP: when
590 { $values { "?" "a generalized boolean" } { "true" quotation } }
591 { $description "If " { $snippet "cond" } " is not " { $link f } ", calls the " { $snippet "true" } " quotation."
592 $nl
593 "The " { $snippet "cond" } " value is removed from the stack before the quotation is called." } ;
594
595 HELP: unless
596 { $values { "?" "a generalized boolean" } { "false" quotation } }
597 { $description "If " { $snippet "cond" } " is " { $link f } ", calls the " { $snippet "false" } " quotation."
598 $nl
599 "The " { $snippet "cond" } " value is removed from the stack before the quotation is called." } ;
600
601 HELP: if*
602 { $values { "?" "a generalized boolean" } { "true" { $quotation "( cond -- ... )" } } { "false" quotation } }
603 { $description "Alternative conditional form that preserves the " { $snippet "cond" } " value if it is true."
604 $nl
605 "If the condition is true, it is retained on the stack before the " { $snippet "true" } " quotation is called. Otherwise, the condition is removed from the stack and the " { $snippet "false" } " quotation is called."
606 $nl
607 "The following two lines are equivalent:"
608 { $code "X [ Y ] [ Z ] if*" "X dup [ Y ] [ drop Z ] if" } } ;
609
610 HELP: when*
611 { $values { "?" "a generalized boolean" } { "true" { $quotation "( cond -- ... )" } } }
612 { $description "Variant of " { $link if* } " with no false quotation."
613 $nl
614 "The following two lines are equivalent:"
615 { $code "X [ Y ] when*" "X dup [ Y ] [ drop ] if" } } ;
616
617 HELP: unless*
618 { $values { "?" "a generalized boolean" } { "false" "a quotation " } }
619 { $description "Variant of " { $link if* } " with no true quotation." }
620 { $notes
621 "The following two lines are equivalent:"
622 { $code "X [ Y ] unless*" "X dup [ ] [ drop Y ] if" } } ;
623
624 HELP: ?if
625 { $values { "default" object } { "cond" "a generalized boolean" } { "true" { $quotation "( cond -- ... )" } } { "false" { $quotation "( default -- ... )" } } }
626 { $description "If the condition is " { $link f } ", the " { $snippet "false" } " quotation is called with the " { $snippet "default" } " value on the stack. Otherwise, the " { $snippet "true" } " quotation is called with the condition on the stack." }
627 { $notes
628 "The following two lines are equivalent:"
629 { $code "[ X ] [ Y ] ?if" "dup [ nip X ] [ drop Y ] if" }
630 "The following two lines are equivalent:"
631 { $code "[ ] [ ] ?if" "swap or" } } ;
632
633 HELP: die
634 { $description "Starts the front-end processor (FEP), which is a low-level debugger which can inspect memory addresses and the like. The FEP is also entered when a critical error occurs." }
635 { $notes
636     "The term FEP originates from the Lisp machines of old. According to the Jargon File,"
637     $nl
638     { $strong "fepped out" } " /fept owt/ " { $emphasis "adj." }  " The Symbolics 3600 LISP Machine has a Front-End Processor called a `FEP' (compare sense 2 of box). When the main processor gets wedged, the FEP takes control of the keyboard and screen. Such a machine is said to have `fepped out' or `dropped into the fep'." 
639     $nl
640     { $url "http://www.jargon.net/jargonfile/f/feppedout.html" }
641 } ;
642
643 HELP: (clone) ( obj -- newobj )
644 { $values { "obj" object } { "newobj" "a shallow copy" } }
645 { $description "Outputs a byte-by-byte copy of the given object. User code should call " { $link clone } " instead." } ;
646
647 HELP: declare
648 { $values { "spec" "an array of class words" } }
649 { $description "Declares that the elements at the top of the stack are instances of the classes in " { $snippet "spec" } "." }
650 { $warning "The compiler blindly trusts declarations, and false declarations can lead to crashes, memory corruption and other undesirable behavior." }
651 { $examples
652     "The optimizer cannot do anything with the below code:"
653     { $code "2 + 10 *" }
654     "However, if we declare that the top of the stack is a " { $link float } ", then type checks and generic dispatch are eliminated, and the compiler can use unsafe intrinsics:"
655     { $code "{ float } declare 2 + 10 *" }
656 } ;
657
658 HELP: tag ( object -- n )
659 { $values { "object" object } { "n" "a tag number" } }
660 { $description "Outputs an object's tag number, between zero and one less than " { $link num-tags } ". This is implementation detail and user code should call " { $link class } " instead." } ;
661
662 HELP: getenv ( n -- obj )
663 { $values { "n" "a non-negative integer" } { "obj" object } }
664 { $description "Reads an object from the Factor VM's environment table. User code never has to read the environment table directly; instead, use one of the callers of this word." } ;
665
666 HELP: setenv ( obj n -- )
667 { $values { "obj" object } { "n" "a non-negative integer" } }
668 { $description "Writes an object to the Factor VM's environment table. User code never has to write to the environment table directly; instead, use one of the callers of this word." } ;
669
670 HELP: object
671 { $class-description
672     "The class of all objects. If a generic word defines a method specializing on this class, the method is used as a fallback, if no other applicable method is found. For instance:"
673     { $code "GENERIC: enclose" "M: number enclose 1array ;" "M: object enclose ;" }
674 } ;
675
676 HELP: null
677 { $class-description
678     "The canonical empty class with no instances."
679 } ;
680
681 HELP: most
682 { $values { "x" object } { "y" object } { "quot" { $quotation "( x y -- ? )" } } { "z" "either " { $snippet "x" } " or " { $snippet "y" } } }
683 { $description "If the quotation yields a true value when applied to " { $snippet "x" } " and " { $snippet "y" } ", outputs " { $snippet "x" } ", otherwise outputs " { $snippet "y" } "." } ;
684
685 HELP: curry
686 { $values { "obj" object } { "quot" callable } { "curry" curry } }
687 { $description "Partial application. Outputs a " { $link callable } " which first pushes " { $snippet "obj" } " and then calls " { $snippet "quot" } "." }
688 { $class-description "The class of objects created by " { $link curry } ". These objects print identically to quotations and implement the sequence protocol, however they only use two cells of storage; a reference to the object and a reference to the underlying quotation." }
689 { $notes "Even if " { $snippet "obj" } " is a word, it will be pushed as a literal."
690 $nl
691 "This operation is efficient and does not copy the quotation." }
692 { $examples
693     { $example "USING: kernel prettyprint ;" "5 [ . ] curry ." "[ 5 . ]" }
694     { $example "USING: kernel prettyprint see ;" "\\ = [ see ] curry ." "[ \\ = see ]" }
695     { $example "USING: kernel math prettyprint sequences ;" "{ 1 2 3 } 2 [ - ] curry map ." "{ -1 0 1 }" }
696 } ;
697
698 HELP: 2curry
699 { $values { "obj1" object } { "obj2" object } { "quot" callable } { "curry" curry } }
700 { $description "Outputs a " { $link callable } " which pushes " { $snippet "obj1" } " and " { $snippet "obj2" } " and then calls " { $snippet "quot" } "." }
701 { $notes "This operation is efficient and does not copy the quotation." }
702 { $examples
703     { $example "USING: kernel math prettyprint ;" "5 4 [ + ] 2curry ." "[ 5 4 + ]" }
704 } ;
705
706 HELP: 3curry
707 { $values { "obj1" object } { "obj2" object } { "obj3" object } { "quot" callable } { "curry" curry } }
708 { $description "Outputs a " { $link callable } " which pushes " { $snippet "obj1" } ", " { $snippet "obj2" } " and " { $snippet "obj3" } ", and then calls " { $snippet "quot" } "." }
709 { $notes "This operation is efficient and does not copy the quotation." } ;
710
711 HELP: with
712 { $values { "param" object } { "obj" object } { "quot" { $quotation "( param elt -- ... )" } } { "obj" object } { "curry" curry } }
713 { $description "Partial application on the left. The following two lines are equivalent:"
714     { $code "swap [ swap A ] curry B" }
715     { $code "[ A ] with B" }
716     
717 }
718 { $notes "This operation is efficient and does not copy the quotation." }
719 { $examples
720     { $example "USING: kernel math prettyprint sequences ;" "2 { 1 2 3 } [ - ] with map ." "{ 1 0 -1 }" }
721 } ;
722
723 HELP: compose
724 { $values { "quot1" callable } { "quot2" callable } { "compose" compose } }
725 { $description "Quotation composition. Outputs a " { $link callable } " which calls " { $snippet "quot1" } " followed by " { $snippet "quot2" } "." }
726 { $notes
727     "The following two lines are equivalent:"
728     { $code
729         "compose call"
730         "append call"
731     }
732     "However, " { $link compose } " runs in constant time, and the optimizing compiler is able to compile code which calls composed quotations."
733 } ;
734
735
736 HELP: prepose
737 { $values { "quot1" callable } { "quot2" callable } { "compose" compose } }
738 { $description "Quotation composition. Outputs a " { $link callable } " which calls " { $snippet "quot2" } " followed by " { $snippet "quot1" } "." }
739 { $notes "See " { $link compose } " for details." } ;
740
741 { compose prepose } related-words
742
743 HELP: dip
744 { $values { "x" object } { "quot" quotation } }
745 { $description "Calls " { $snippet "quot" } " with " { $snippet "obj" } " hidden on the retain stack." }
746 { $examples
747     { $example "USING: arrays kernel math prettyprint ;" "10 20 30 [ / ] dip 2array ." "{ 1/2 30 }" }
748 } ;
749
750 HELP: 2dip
751 { $values { "x" object } { "y" object } { "quot" quotation } }
752 { $description "Calls " { $snippet "quot" } " with " { $snippet "x" } " and " { $snippet "y" } " hidden on the retain stack." }
753 { $notes "The following are equivalent:"
754     { $code "[ [ foo bar ] dip ] dip" }
755     { $code "[ foo bar ] 2dip" }
756 } ;
757
758 HELP: 3dip
759 { $values { "x" object } { "y" object } { "z" object } { "quot" quotation } }
760 { $description "Calls " { $snippet "quot" } " with " { $snippet "x" } ", " { $snippet "y" } " and " { $snippet "z" } " hidden on the retain stack." }
761 { $notes "The following are equivalent:"
762     { $code "[ [ [ foo bar ] dip ] dip ] dip" }
763     { $code "[ foo bar ] 3dip" }
764 } ;
765
766 HELP: 4dip
767 { $values { "w" object } { "x" object } { "y" object } { "z" object } { "quot" quotation } }
768 { $description "Calls " { $snippet "quot" } " with " { $snippet "w" } ", " { $snippet "x" } ", " { $snippet "y" } " and " { $snippet "z" } " hidden on the retain stack." }
769 { $notes "The following are equivalent:"
770     { $code "[ [ [ [ foo bar ] dip ] dip ] dip ] dip" }
771     { $code "[ foo bar ] 4dip" }
772 } ;
773
774 HELP: while
775 { $values { "pred" { $quotation "( -- ? )" } } { "body" "a quotation" } }
776 { $description "Calls " { $snippet "body" } " until " { $snippet "pred" } " returns " { $link f } "." } ;
777
778 HELP: until
779 { $values { "pred" { $quotation "( -- ? )" } } { "body" "a quotation" } }
780 { $description "Calls " { $snippet "body" } " until " { $snippet "pred" } " returns " { $link t } "." } ;
781
782 HELP: do
783 { $values { "pred" { $quotation "( -- ? )" } } { "body" "a quotation" } }
784 { $description "Executes one iteration of a " { $link while } " or " { $link until } " loop." } ;
785
786 HELP: loop
787 { $values
788      { "pred" quotation } }
789      { $description "Calls the quotation repeatedly until it outputs " { $link f } "." }
790 { $examples "Loop until we hit a zero:"
791     { $unchecked-example "USING: kernel random math io ; "
792     " [ \"hi\" write bl 10 random zero? not ] loop"
793     "hi hi hi" }
794     "A fun loop:"
795     { $example "USING: kernel prettyprint math ; "
796     "3 [ dup . 7 + 11 mod dup 3 = not ] loop drop"
797     "3\n10\n6\n2\n9\n5\n1\n8\n4\n0\n7" }
798 } ;
799
800 ARTICLE: "looping-combinators" "Looping combinators"
801 "In most cases, loops should be written using high-level combinators (such as " { $link "sequences-combinators" } ") or tail recursion. However, sometimes, the best way to express intent is with a loop."
802 { $subsections
803     while
804     until
805 }
806 "To execute one iteration of a loop, use the following word:"
807 { $subsections do }
808 "This word is intended as a modifier. The normal " { $link while } " loop never executes the body if the predicate returns false on the first iteration. To ensure the body executes at least once, use " { $link do } ":"
809 { $code
810     "[ P ] [ Q ] do while"
811 }
812 "A simpler looping combinator which executes a single quotation until it returns " { $link f } ":"
813 { $subsections loop } ;
814
815 HELP: assert
816 { $values { "got" "the obtained value" } { "expect" "the expected value" } }
817 { $description "Throws an " { $link assert } " error." }
818 { $error-description "Thrown when a unit test or other assertion fails." } ;
819
820 HELP: assert=
821 { $values { "a" object } { "b" object } }
822 { $description "Throws an " { $link assert } " error if " { $snippet "a" } " does not equal " { $snippet "b" } "." } ;
823
824 ARTICLE: "shuffle-words" "Shuffle words"
825 "Shuffle words rearrange items at the top of the data stack. They control the flow of data between words that perform actions."
826 $nl
827 "The " { $link "cleave-combinators" } ", " { $link "spread-combinators" } " and " { $link "apply-combinators" } " are closely related to shuffle words and should be used instead where possible because they can result in clearer code; also, see the advice in " { $link "cookbook-philosophy" } "."
828 $nl
829 "Removing stack elements:"
830 { $subsections
831     drop
832     2drop
833     3drop
834     nip
835     2nip
836 }
837 "Duplicating stack elements:"
838 { $subsections
839     dup
840     2dup
841     3dup
842     dupd
843     over
844     2over
845     pick
846     tuck
847 }
848 "Permuting stack elements:"
849 { $subsections
850     swap
851     swapd
852     rot
853     -rot
854     spin
855     roll
856     -roll
857 } ;
858
859 ARTICLE: "equality" "Equality"
860 "There are two distinct notions of “sameness” when it comes to objects."
861 $nl
862 "You can test if two references point to the same object (" { $emphasis "identity comparison" } "). This is rarely used; it is mostly useful with large, mutable objects where the object identity matters but the value is transient:"
863 { $subsections eq? }
864 "You can test if two objects are equal in a domain-specific sense, usually by being instances of the same class, and having equal slot values (" { $emphasis "value comparison" } "):"
865 { $subsections = }
866 "A third form of equality is provided by " { $link number= } ". It compares numeric value while disregarding types."
867 $nl
868 "Custom value comparison methods for use with " { $link = } " can be defined on a generic word:"
869 { $subsections equal? }
870 "Utility class:"
871 { $subsections identity-tuple }
872 "An object can be cloned; the clone has distinct identity but equal value:"
873 { $subsections clone } ;
874
875 ARTICLE: "assertions" "Assertions"
876 "Some words to make assertions easier to enforce:"
877 { $subsections
878     assert
879     assert=
880 } ;
881