]> gitweb.factorcode.org Git - factor.git/blob - core/kernel/kernel-docs.factor
a484139bc0c7fa2c80180ae73067a6fb519ec385
[factor.git] / core / kernel / kernel-docs.factor
1 USING: alien arrays classes combinators heaps help.markup help.syntax
2 kernel.private layouts math quotations sequences system threads words ;
3 IN: kernel
4
5 HELP: OBJ-CURRENT-THREAD
6 { $description "Contains a reference to the running " { $link thread } " instance." } ;
7
8 HELP: JIT-PUSH-LITERAL
9 { $description "JIT code template for pushing literals unto the datastack." } ;
10
11 HELP: OBJ-SAMPLE-CALLSTACKS
12 { $description "A " { $link sequence } " that contains all call frames that is being captured during sampling profiling. See the " { $vocab-link "tools.profiler.sampling" } " vocab." } ;
13
14 HELP: OBJ-SLEEP-QUEUE
15 { $description "A " { $link min-heap } " containing sleeping threads." }
16 { $see-also sleep-queue } ;
17
18 HELP: OBJ-UNDEFINED
19 { $description "Default definition for undefined words" } ;
20
21 HELP: WIN-EXCEPTION-HANDLER
22 { $description "This special object is an " { $link alien } " containing a pointer to the processes global exception handler. Only applicable on " { $link windows } "." } ;
23
24 HELP: eq?
25 { $values { "obj1" object } { "obj2" object } { "?" boolean } }
26 { $description "Tests if two references point at the same object." } ;
27
28 HELP: drop  $shuffle ;
29 HELP: 2drop $shuffle ;
30 HELP: 3drop $shuffle ;
31 HELP: 4drop $shuffle ;
32 HELP: dup   $shuffle ;
33 HELP: 2dup  $shuffle ;
34 HELP: 3dup  $shuffle ;
35 HELP: 4dup  $shuffle ;
36 HELP: nip   $shuffle ;
37 HELP: 2nip  $shuffle ;
38 HELP: over  $shuffle ;
39 HELP: 2over $shuffle ;
40 HELP: pick  $shuffle ;
41 HELP: swap  $shuffle ;
42
43 HELP: rot   $complex-shuffle ;
44 HELP: -rot  $complex-shuffle ;
45 HELP: dupd  $complex-shuffle ;
46 HELP: swapd $complex-shuffle ;
47
48 HELP: callstack>array
49 { $values { "callstack" callstack } { "array" array } }
50 { $description "Converts the callstack to an array containing groups of three elements. The array is in reverse order so that the innermost frame comes first." } ;
51
52 HELP: get-datastack
53 { $values { "array" array } }
54 { $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." } ;
55
56 HELP: set-datastack
57 { $values { "array" array } }
58 { $description "Replaces the data stack contents with a copy of an array. The end of the array becomes the top of the stack." } ;
59
60 HELP: get-retainstack
61 { $values { "array" array } }
62 { $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." } ;
63
64 HELP: set-retainstack
65 { $values { "array" array } }
66 { $description "Replaces the retain stack contents with a copy of an array. The end of the array becomes the top of the stack." } ;
67
68 HELP: get-callstack
69 { $values { "callstack" callstack } }
70 { $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. Each group of three elements in the callstack is frame:"
71   { $list
72     "The first element is the executing word or quotation."
73     "The second element is the executing quotation."
74     "The third element is the offset in the executing quotation, or -1 if the offset can't be determined."
75   }
76 } ;
77
78 HELP: set-callstack
79 { $values { "callstack" callstack } }
80 { $description "Replaces the call stack contents. Control flow is transferred immediately to the innermost frame of the new call stack." } ;
81
82 HELP: clear
83 { $description "Clears the data stack." } ;
84
85 HELP: build
86 { $values { "n" integer } }
87 { $description "The current build number. Factor increments this number whenever a new boot image is created." } ;
88
89 HELP: leaf-signal-handler
90 { $description "A word called by the VM when a VM error occurs." } ;
91
92 HELP: hashcode*
93 { $values { "depth" integer } { "obj" object } { "code" fixnum } }
94 { $contract "Outputs the hashcode of an object. The hashcode operation must satisfy the following properties:"
95 { $list
96     { "If two objects are equal under " { $link = } ", they must have equal hashcodes." }
97     { "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," }
98     { "The hashcode should be a " { $link fixnum } ", however returning a " { $link bignum } " will not cause any problems other than potential performance degradation." }
99     { "The hashcode is only permitted to change between two invocations if the object or one of its slot values was mutated." }
100 }
101 "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." } ;
102
103 HELP: hashcode
104 { $values { "obj" object } { "code" fixnum } }
105 { $description "Computes the hashcode of an object with a default hashing depth. See " { $link hashcode* } " for the hashcode contract." } ;
106
107 HELP: identity-hashcode
108 { $values { "obj" object } { "code" fixnum } }
109 { $description "Outputs the identity hashcode of an object. The identity hashcode is not guaranteed to be unique, however it will not change during the object's lifetime." } ;
110
111 { hashcode hashcode* identity-hashcode } related-words
112
113 HELP: =
114 { $values { "obj1" object } { "obj2" object } { "?" boolean } }
115 { $description
116     "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."
117 }
118 { $examples
119     { $example "USING: kernel prettyprint ;" "5 5 = ." "t" }
120     { $example "USING: kernel prettyprint ;" "5 005 = ." "t" }
121     { $example "USING: kernel prettyprint ;" "5 5.0 = ." "f" }
122     { $example "USING: arrays kernel prettyprint ;" "{ \"a\" \"b\" } \"a\" \"b\" 2array = ." "t" }
123     { $example "USING: arrays kernel prettyprint ;" "{ \"a\" \"b\" } [ \"a\" \"b\" ] = ." "f" }
124 } ;
125
126 HELP: equal?
127 { $values { "obj1" object } { "obj2" object } { "?" boolean } }
128 { $contract
129     "Tests if two objects are equal."
130     $nl
131     "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."
132     $nl
133     "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:"
134     { $list
135         { { $snippet "a = b" } " implies " { $snippet "b = a" } }
136         { { $snippet "a = b" } " and " { $snippet "b = c" } " implies " { $snippet "a = c" } }
137     }
138     "If a class defines a custom equality comparison test, it should also define a compatible method for the " { $link hashcode* } " generic word."
139 }
140 { $examples
141     "An example demonstrating why this word should only be used to define methods on, and never called directly:"
142     { $example "USING: kernel prettyprint ;" "5 5 equal? ." "f" }
143     "Using " { $link = } " gives the expected behavior:"
144     { $example "USING: kernel prettyprint ;" "5 5 = ." "t" }
145 } ;
146
147 HELP: identity-tuple
148 { $class-description "A class defining an " { $link equal? } " method which always returns f." }
149 { $examples
150     "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:"
151     { $code "TUPLE: foo < identity-tuple ;" }
152     "By calling " { $link = } " on instances of " { $snippet "foo" } " we get the results we expect:"
153     { $unchecked-example "T{ foo } dup = ." "t" }
154     { $unchecked-example "T{ foo } dup clone = ." "f" }
155 } ;
156
157 HELP: clone
158 { $values { "obj" object } { "cloned" "a new object" } }
159 { $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." } ;
160
161 HELP: ?
162 { $values { "?" "a generalized boolean" } { "true" object } { "false" object } { "true/false" { { $snippet "true" } " or " { $snippet "false" } } } }
163 { $description "Chooses between two values depending on the boolean value of " { $snippet "cond" } "." } ;
164
165 HELP: boolean
166 { $class-description "A union of the " { $link POSTPONE: t } " and " { $link POSTPONE: f } " classes." } ;
167
168 HELP: >boolean
169 { $values { "obj" "a generalized boolean" } { "?" boolean } }
170 { $description "Convert a generalized boolean into a boolean. That is, " { $link f } " retains its value, whereas anything else becomes " { $link t } "." } ;
171
172 HELP: not
173 { $values { "obj" "a generalized boolean" } { "?" boolean } }
174 { $description "For " { $link f } " outputs " { $link t } " and for anything else outputs " { $link f } "." }
175 { $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." } ;
176
177 HELP: and
178 { $values { "obj1" "a generalized boolean" } { "obj2" "a generalized boolean" } { "?" "a generalized boolean" } }
179 { $description "If both inputs are true, outputs " { $snippet "obj2" } ". otherwise outputs " { $link f } "." }
180 { $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." }
181 { $examples
182     "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:"
183     { $example "USING: kernel prettyprint ;" "t f and ." "f" }
184     { $example "USING: kernel prettyprint ;" "t 7 and ." "7" }
185     { $example "USING: kernel prettyprint ;" "\"hi\" 12.0 and ." "12.0" }
186 } ;
187
188 HELP: or
189 { $values { "obj1" "a generalized boolean" } { "obj2" "a generalized boolean" } { "?" "a generalized boolean" } }
190 { $description "If both inputs are false, outputs " { $link f } ". otherwise outputs the first of " { $snippet "obj1" } " and " { $snippet "obj2" } " which is true." }
191 { $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." }
192 { $examples
193     "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:"
194     { $example "USING: kernel prettyprint ;" "t f or ." "t" }
195     { $example "USING: kernel prettyprint ;" "\"hi\" 12.0 or ." "\"hi\"" }
196 } ;
197
198 HELP: xor
199 { $values { "obj1" "a generalized boolean" } { "obj2" "a generalized boolean" } { "?" "a generalized boolean" } }
200 { $description "If exactly one input is false, outputs the other input. Otherwise outputs " { $link f } "." }
201 { $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." } ;
202
203 HELP: both?
204 { $values { "x" object } { "y" object } { "quot" { $quotation ( ... obj -- ... ? ) } } { "?" boolean } }
205 { $description "Tests if the quotation yields a true value when applied to both " { $snippet "x" } " and " { $snippet "y" } "." }
206 { $examples
207     { $example "USING: kernel math prettyprint ;" "3 5 [ odd? ] both? ." "t" }
208     { $example "USING: kernel math prettyprint ;" "12 7 [ even? ] both? ." "f" }
209 } ;
210
211 HELP: either?
212 { $values { "x" object } { "y" object } { "quot" { $quotation ( ... obj -- ... ? ) } } { "?" boolean } }
213 { $description "Tests if the quotation yields a true value when applied to either " { $snippet "x" } " or " { $snippet "y" } "." }
214 { $examples
215     { $example "USING: kernel math prettyprint ;" "3 6 [ odd? ] either? ." "t" }
216     { $example "USING: kernel math prettyprint ;" "5 7 [ even? ] either? ." "f" }
217 } ;
218
219 HELP: same?
220 { $values { "x" object } { "y" object } { "quot" { $quotation ( ... obj -- ... obj' ) } } { "?" boolean } }
221 { $description "Applies the quotation to both " { $snippet "x" } " and " { $snippet "y" } ", and then checks if the results are equal." }
222 { $examples
223     { $example "USING: kernel math prettyprint ;" "4 5 [ 2/ ] same? ." "t" }
224     { $example "USING: kernel math prettyprint ;" "3 7 [ sq ] same? ." "f" }
225 } ;
226
227 HELP: execute
228 { $values { "word" word } }
229 { $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." }
230 { $examples
231     { $example "USING: kernel io words ;" "IN: scratchpad" ": twice ( word -- ) dup execute execute ; inline\n: hello ( -- ) \"Hello\" print ;\n\\ hello twice" "Hello\nHello" }
232 } ;
233
234 { execute POSTPONE: execute( } related-words
235
236 HELP: (execute)
237 { $values { "word" word } }
238 { $description "Executes a word without checking if it is a word first." }
239 { $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." } ;
240
241 HELP: call
242 { $values { "callable" callable } }
243 { $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." }
244 { $examples
245     "The following two lines are equivalent:"
246     { $code "2 [ 2 + 3 * ] call" "2 2 + 3 *" }
247 } ;
248
249 { call POSTPONE: call( } related-words
250
251 HELP: keep
252 { $values { "x" object } { "quot" { $quotation ( ..a x -- ..b ) } } }
253 { $description "Call a quotation with a value on the stack, restoring the value when the quotation returns." }
254 { $examples
255     { $example "USING: arrays kernel prettyprint ;" "2 \"greetings\" [ <array> ] keep 2array ." "{ { \"greetings\" \"greetings\" } \"greetings\" }" }
256 } ;
257
258 HELP: 2keep
259 { $values { "x" object } { "y" object } { "quot" { $quotation ( ..a x y -- ..b ) } } }
260 { $description "Call a quotation with two values on the stack, restoring the values when the quotation returns." } ;
261
262 HELP: 3keep
263 { $values { "x" object } { "y" object } { "z" object } { "quot" { $quotation ( ..a x y z -- ..b ) } } }
264 { $description "Call a quotation with three values on the stack, restoring the values when the quotation returns." } ;
265
266 HELP: bi
267 { $values { "x" object } { "p" { $quotation ( ..a x -- ..b ) } } { "q" { $quotation ( ..c x -- ..d ) } } }
268 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "x" } "." }
269 { $examples
270     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x -- )" } ", then the following two lines are equivalent:"
271     { $code
272         "[ p ] [ q ] bi"
273         "dup p q"
274     }
275     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x -- y )" } ", then the following two lines are equivalent:"
276     { $code
277         "[ p ] [ q ] bi"
278         "dup p swap q"
279     }
280     "In general, the following two lines are equivalent:"
281     { $code
282         "[ p ] [ q ] bi"
283         "[ p ] keep q"
284     }
285
286 } ;
287
288 HELP: 2bi
289 { $values { "x" object } { "y" object } { "p" { $quotation ( x y -- ... ) } } { "q" { $quotation ( x y -- ... ) } } }
290 { $description "Applies " { $snippet "p" } " to the two input values, then applies " { $snippet "q" } " to the two input values." }
291 { $examples
292     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x y -- )" } ", then the following two lines are equivalent:"
293     { $code
294         "[ p ] [ q ] 2bi"
295         "2dup p q"
296     }
297     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x y -- z )" } ", then the following two lines are equivalent:"
298     { $code
299         "[ p ] [ q ] 2bi"
300         "2dup p -rot q"
301     }
302     "In general, the following two lines are equivalent:"
303     { $code
304         "[ p ] [ q ] 2bi"
305         "[ p ] 2keep q"
306     }
307 } ;
308
309 HELP: 3bi
310 { $values { "x" object } { "y" object } { "z" object } { "p" { $quotation ( x y z -- ... ) } } { "q" { $quotation ( x y z -- ... ) } } }
311 { $description "Applies " { $snippet "p" } " to the three input values, then applies " { $snippet "q" } " to the three input values." }
312 { $examples
313     "If " { $snippet "[ p ]" } " and " { $snippet "[ q ]" } " have stack effect " { $snippet "( x y z -- )" } ", then the following two lines are equivalent:"
314     { $code
315         "[ p ] [ q ] 3bi"
316         "3dup p q"
317     }
318     "In general, the following two lines are equivalent:"
319     { $code
320         "[ p ] [ q ] 3bi"
321         "[ p ] 3keep q"
322     }
323 } ;
324
325 HELP: tri
326 { $values { "x" object } { "p" { $quotation ( x -- ... ) } } { "q" { $quotation ( x -- ... ) } } { "r" { $quotation ( x -- ... ) } } }
327 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "x" } ", and finally applies " { $snippet "r" } " to " { $snippet "x" } "." }
328 { $examples
329     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x -- )" } ", then the following two lines are equivalent:"
330     { $code
331         "[ p ] [ q ] [ r ] tri"
332         "dup p dup q r"
333     }
334     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x -- y )" } ", then the following two lines are equivalent:"
335     { $code
336         "[ p ] [ q ] [ r ] tri"
337         "dup p over q rot r"
338     }
339     "In general, the following two lines are equivalent:"
340     { $code
341         "[ p ] [ q ] [ r ] tri"
342         "[ p ] keep [ q ] keep r"
343     }
344 } ;
345
346 HELP: 2tri
347 { $values { "x" object } { "y" object } { "p" { $quotation ( x y -- ... ) } } { "q" { $quotation ( x y -- ... ) } } { "r" { $quotation ( x y -- ... ) } } }
348 { $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." }
349 { $examples
350     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x y -- )" } ", then the following two lines are equivalent:"
351     { $code
352         "[ p ] [ q ] [ r ] 2tri"
353         "2dup p 2dup q r"
354     }
355     "In general, the following two lines are equivalent:"
356     { $code
357         "[ p ] [ q ] [ r ] 2tri"
358         "[ p ] 2keep [ q ] 2keep r"
359     }
360 } ;
361
362 HELP: 3tri
363 { $values { "x" object } { "y" object } { "z" object } { "p" { $quotation ( x y z -- ... ) } } { "q" { $quotation ( x y z -- ... ) } } { "r" { $quotation ( x y z -- ... ) } } }
364 { $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." }
365 { $examples
366     "If " { $snippet "[ p ]" } ", " { $snippet "[ q ]" } " and " { $snippet "[ r ]" } " have stack effect " { $snippet "( x y z -- )" } ", then the following two lines are equivalent:"
367     { $code
368         "[ p ] [ q ] [ r ] 3tri"
369         "3dup p 3dup q r"
370     }
371     "In general, the following two lines are equivalent:"
372     { $code
373         "[ p ] [ q ] [ r ] 3tri"
374         "[ p ] 3keep [ q ] 3keep r"
375     }
376 } ;
377
378
379 HELP: bi*
380 { $values { "x" object } { "y" object } { "p" { $quotation ( x -- ... ) } } { "q" { $quotation ( y -- ... ) } } }
381 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "y" } "." }
382 { $examples
383     "The following two lines are equivalent:"
384     { $code
385         "[ p ] [ q ] bi*"
386         "[ p ] dip q"
387     }
388 } ;
389
390 HELP: 2bi*
391 { $values { "w" object } { "x" object } { "y" object } { "z" object } { "p" { $quotation ( w x -- ... ) } } { "q" { $quotation ( y z -- ... ) } } }
392 { $description "Applies " { $snippet "p" } " to " { $snippet "w" } " and " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "y" } " and " { $snippet "z" } "." }
393 { $examples
394     "The following two lines are equivalent:"
395     { $code
396         "[ p ] [ q ] 2bi*"
397         "[ p ] 2dip q"
398     }
399 } ;
400
401 HELP: 2tri*
402 { $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 -- ... ) } } }
403 { $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" } "." }
404 { $examples
405     "The following two lines are equivalent:"
406     { $code
407         "[ p ] [ q ] [ r ] 2tri*"
408         "[ [ p ] 2dip q ] 2dip r"
409     }
410 } ;
411
412 HELP: tri*
413 { $values { "x" object } { "y" object } { "z" object } { "p" { $quotation ( x -- ... ) } } { "q" { $quotation ( y -- ... ) } } { "r" { $quotation ( z -- ... ) } } }
414 { $description "Applies " { $snippet "p" } " to " { $snippet "x" } ", then applies " { $snippet "q" } " to " { $snippet "y" } ", and finally applies " { $snippet "r" } " to " { $snippet "z" } "." }
415 { $examples
416     "The following two lines are equivalent:"
417     { $code
418         "[ p ] [ q ] [ r ] tri*"
419         "[ [ p ] dip q ] dip r"
420     }
421 } ;
422
423 HELP: bi@
424 { $values { "x" object } { "y" object } { "quot" { $quotation ( obj -- ... ) } } }
425 { $description "Applies the quotation to " { $snippet "x" } ", then to " { $snippet "y" } "." }
426 { $examples
427     "The following two lines are equivalent:"
428     { $code
429         "[ p ] bi@"
430         "[ p ] dip p"
431     }
432     "The following two lines are also equivalent:"
433     { $code
434         "[ p ] bi@"
435         "[ p ] [ p ] bi*"
436     }
437 } ;
438
439 HELP: 2bi@
440 { $values { "w" object } { "x" object } { "y" object } { "z" object } { "quot" { $quotation ( obj1 obj2 -- ... ) } } }
441 { $description "Applies the quotation to " { $snippet "w" } " and " { $snippet "x" } ", then to " { $snippet "y" } " and " { $snippet "z" } "." }
442 { $examples
443     "The following two lines are equivalent:"
444     { $code
445         "[ p ] 2bi@"
446         "[ p ] 2dip p"
447     }
448     "The following two lines are also equivalent:"
449     { $code
450         "[ p ] 2bi@"
451         "[ p ] [ p ] 2bi*"
452     }
453 } ;
454
455 HELP: tri@
456 { $values { "x" object } { "y" object } { "z" object } { "quot" { $quotation ( obj -- ... ) } } }
457 { $description "Applies the quotation to " { $snippet "x" } ", then to " { $snippet "y" } ", and finally to " { $snippet "z" } "." }
458 { $examples
459     "The following two lines are equivalent:"
460     { $code
461         "[ p ] tri@"
462         "[ [ p ] dip p ] dip p"
463     }
464     "The following two lines are also equivalent:"
465     { $code
466         "[ p ] tri@"
467         "[ p ] [ p ] [ p ] tri*"
468     }
469 } ;
470
471 HELP: 2tri@
472 { $values { "u" object } { "v" object } { "w" object } { "x" object } { "y" object } { "z" object } { "quot" { $quotation ( obj1 obj2 -- ... ) } } }
473 { $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" } "." }
474 { $examples
475     "The following two lines are equivalent:"
476     { $code
477         "[ p ] 2tri@"
478         "[ [ p ] 2dip p ] 2dip p"
479     }
480     "The following two lines are also equivalent:"
481     { $code
482         "[ p ] 2tri@"
483         "[ p ] [ p ] [ p ] 2tri*"
484     }
485 } ;
486
487 HELP: bi-curry
488 { $values { "x" object } { "p" { $quotation ( x -- ... ) } } { "q" { $quotation ( x -- ... ) } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ x q ]" } } }
489 { $description "Partially applies " { $snippet "p" } " and " { $snippet "q" } " to " { $snippet "x" } "." }
490 { $notes
491   "The following two lines are equivalent:"
492   { $code
493     "[ p ] [ q ] bi-curry [ call ] bi@"
494     "[ p ] [ q ] bi"
495   }
496   "Higher-arity variants of " { $link bi } " can be built from " { $link bi-curry } ":"
497   { $code
498     "[ p ] [ q ] bi-curry bi == [ p ] [ q ] 2bi"
499     "[ p ] [ q ] bi-curry bi-curry bi == [ p ] [ q ] 3bi"
500   }
501   "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* } ":"
502   { $code
503     "[ p ] [ q ] bi-curry bi*"
504     "[ swap ] keep [ p ] [ q ] 2bi*"
505   }
506   "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" } "."
507 } ;
508
509 HELP: tri-curry
510 { $values
511   { "x" object }
512   { "p" { $quotation ( x -- ... ) } }
513   { "q" { $quotation ( x -- ... ) } }
514   { "r" { $quotation ( x -- ... ) } }
515   { "p'" { $snippet "[ x p ]" } }
516   { "q'" { $snippet "[ x q ]" } }
517   { "r'" { $snippet "[ x r ]" } }
518 }
519 { $description "Partially applies " { $snippet "p" } ", " { $snippet "q" } " and " { $snippet "r" } " to " { $snippet "x" } "." }
520 { $notes
521   "The following two lines are equivalent:"
522   { $code
523     "[ p ] [ q ] [ r ] tri-curry [ call ] tri@"
524     "[ p ] [ q ] [ r ] tri"
525   }
526   "Higher-arity variants of " { $link tri } " can be built from " { $link tri-curry } ":"
527   { $code
528     "[ p ] [ q ] [ r ] tri-curry tri == [ p ] [ q ] [ r ] 2tri"
529     "[ p ] [ q ] [ r ] tri-curry tri-curry bi == [ p ] [ q ] [ r ] 3tri"
530   }
531   "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" } "." } ;
532
533 HELP: bi-curry*
534 { $values { "x" object } { "y" object } { "p" { $quotation ( x -- ... ) } } { "q" { $quotation ( y -- ... ) } } { "p'" { $snippet "[ x p ]" } } { "q'" { $snippet "[ y q ]" } } }
535 { $description "Partially applies " { $snippet "p" } " to " { $snippet "x" } ", and " { $snippet "q" } " to " { $snippet "y" } "." }
536 { $notes
537   "The following two lines are equivalent:"
538   { $code
539     "[ p ] [ q ] bi-curry* [ call ] bi@"
540     "[ p ] [ q ] bi*"
541   }
542   "The combination " { $snippet "bi-curry* bi" } " is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
543   { $code
544     "[ p ] [ q ] bi-curry* bi"
545     "[ over ] dip [ p ] [ q ] 2bi*"
546   }
547   "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" } "."
548   $nl
549   "The combination " { $snippet "bi-curry* bi*" } " is equivalent to a stack shuffle preceding " { $link 2bi* } ":"
550   { $code
551     "[ p ] [ q ] bi-curry* bi*"
552     "[ swap ] dip [ p ] [ q ] 2bi*"
553   }
554   "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" } "."
555
556 } ;
557
558 HELP: tri-curry*
559 { $values
560   { "x" object }
561   { "y" object }
562   { "z" object }
563   { "p" { $quotation ( x -- ... ) } }
564   { "q" { $quotation ( y -- ... ) } }
565   { "r" { $quotation ( z -- ... ) } }
566   { "p'" { $snippet "[ x p ]" } }
567   { "q'" { $snippet "[ y q ]" } }
568   { "r'" { $snippet "[ z r ]" } }
569 }
570 { $description "Partially applies " { $snippet "p" } " to " { $snippet "x" } ", " { $snippet "q" } " to " { $snippet "y" } " and " { $snippet "r" } " to " { $snippet "z" } "." }
571 { $notes
572   "The following two lines are equivalent:"
573   { $code
574     "[ p ] [ q ] [ r ] tri-curry* [ call ] tri@"
575     "[ p ] [ q ] [ r ] tri*"
576   }
577   "The combination " { $snippet "tri-curry* tri" } " is equivalent to a stack shuffle preceding " { $link 2tri* } ":"
578   { $code
579     "[ p ] [ q ] [ r ] tri-curry* tri"
580     "[ [ over ] dip over ] dip [ p ] [ q ] [ r ] 2tri*"
581   }
582 } ;
583
584 HELP: bi-curry@
585 { $values { "x" object } { "y" object } { "q" { $quotation ( obj -- ... ) } } { "p'" { $snippet "[ x q ]" } } { "q'" { $snippet "[ y q ]" } } }
586 { $description "Partially applies " { $snippet "q" } " to " { $snippet "x" } " and " { $snippet "y" } "." }
587 { $notes
588   "The following two lines are equivalent:"
589   { $code
590     "[ q ] bi-curry@"
591     "[ q ] [ q ] bi-curry*"
592   }
593 } ;
594
595 HELP: tri-curry@
596 { $values
597   { "x" object }
598   { "y" object }
599   { "z" object }
600   { "q" { $quotation ( obj -- ... ) } }
601   { "p'" { $snippet "[ x q ]" } }
602   { "q'" { $snippet "[ y q ]" } }
603   { "r'" { $snippet "[ z q ]" } }
604 }
605 { $description "Partially applies " { $snippet "q" } " to " { $snippet "x" } ", " { $snippet "y" } " and " { $snippet "z" } "." }
606 { $notes
607   "The following two lines are equivalent:"
608   { $code
609     "[ q ] tri-curry@"
610     "[ q ] [ q ] [ q ] tri-curry*"
611   }
612 } ;
613
614 HELP: if
615 { $values { "?" "a generalized boolean" } { "true" quotation } { "false" quotation } }
616 { $description "If " { $snippet "cond" } " is " { $link f } ", calls the " { $snippet "false" } " quotation. Otherwise calls the " { $snippet "true" } " quotation."
617 $nl
618 "The " { $snippet "cond" } " value is removed from the stack before either quotation is called." }
619 { $examples
620     { $example
621         "USING: io kernel math ;"
622         "10 3 < [ \"Math is broken\" print ] [ \"Math is good\" print ] if"
623         "Math is good"
624     }
625 }
626 { $notes { $snippet "if" } " is executed as a primitive when preceded by two literal quotations. The below definition is not executed unless one of its arguments is a non-literal quotation, such as a quotation constructed with " { $link curry } " or " { $link compose } ", or for " { $link "fry" } " or quotations including " { $link "locals" } "." } ;
627
628 HELP: when
629 { $values { "?" "a generalized boolean" } { "true" quotation } }
630 { $description "If " { $snippet "cond" } " is not " { $link f } ", calls the " { $snippet "true" } " quotation."
631 $nl
632 "The " { $snippet "cond" } " value is removed from the stack before the quotation is called." }
633 { $examples
634     { $example
635         "USING: kernel math prettyprint ;"
636         "-5 dup 0 < [ 3 + ] when ."
637         "-2"
638     }
639 } ;
640
641 HELP: unless
642 { $values { "?" "a generalized boolean" } { "false" quotation } }
643 { $description "If " { $snippet "cond" } " is " { $link f } ", calls the " { $snippet "false" } " quotation."
644 $nl
645 "The " { $snippet "cond" } " value is removed from the stack before the quotation is called." }
646 { $examples
647     { $example
648         "USING: kernel math prettyprint sequences ;"
649         "IN: scratchpad"
650         ""
651         "CONSTANT: american-cities {"
652         "    \"San Francisco\""
653         "    \"Los Angeles\""
654         "    \"New York\""
655         "}"
656         ""
657         ": add-tax ( price city -- price' )"
658         "    american-cities member? [ 1.1 * ] unless ;"
659         ""
660         "123 \"Ottawa\" add-tax ."
661         "135.3"
662     }
663 } ;
664
665 HELP: if*
666 { $values { "?" "a generalized boolean" } { "true" { $quotation ( ..a ? -- ..b ) } } { "false" { $quotation ( ..a -- ..b ) } } }
667 { $description "Alternative conditional form that preserves the " { $snippet "cond" } " value if it is true."
668 $nl
669 "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."
670 $nl
671 "The following two lines are equivalent:"
672 { $code "X [ Y ] [ Z ] if*" "X dup [ Y ] [ drop Z ] if" } }
673 { $examples
674     "Notice how in this example, the same value is tested by the conditional, and then used in the true branch; the false branch does not need to drop the value because of how " { $link if* } " works:"
675     { $example
676         "USING: assocs io kernel math.parser ;"
677         "IN: scratchpad"
678         ""
679         ": curry-price ( meat -- price )
680     {
681         { \"Beef\" 10 }
682         { \"Chicken\" 12 }
683         { \"Lamb\" 13 }
684     } at ;
685
686 : order-curry ( meat -- )
687     curry-price [
688         \"Your order will be \" write
689         number>string write
690         \" dollars.\" write
691     ] [ \"Invalid order.\" print ] if* ;"
692         ""
693         "\"Deer\" order-curry"
694         "Invalid order."
695     }
696 } ;
697
698 HELP: when*
699 { $values { "?" "a generalized boolean" } { "true" { $quotation ( ..a ? -- ..a ) } } }
700 { $description "Variant of " { $link if* } " with no false quotation."
701 $nl
702 "The following two lines are equivalent:"
703 { $code "X [ Y ] when*" "X dup [ Y ] [ drop ] if" } } ;
704
705 HELP: unless*
706 { $values { "?" "a generalized boolean" } { "false" { $quotation ( ..a -- ..a x ) } } { "x" object } }
707 { $description "Variant of " { $link if* } " with no true quotation." }
708 { $notes
709 "The following two lines are equivalent:"
710 { $code "X [ Y ] unless*" "X dup [ ] [ drop Y ] if" } } ;
711
712 HELP: ?if
713 { $values { "default" object } { "cond" "a generalized boolean" } { "true" { $quotation ( ..a cond -- ..b ) } } { "false" { $quotation ( ..a default -- ..b ) } } }
714 { $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." }
715 { $notes
716 "The following two lines are equivalent:"
717 { $code "[ X ] [ Y ] ?if" "dup [ nip X ] [ drop Y ] if" }
718 "The following two lines are equivalent:"
719 { $code "[ ] [ ] ?if" "swap or" } } ;
720
721 HELP: die
722 { $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." }
723 { $notes
724     "The term FEP originates from the Lisp machines of old. According to the Jargon File,"
725     $nl
726     { $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'."
727     $nl
728     { $url "http://www.jargon.net/jargonfile/f/feppedout.html" }
729 } ;
730
731 HELP: (clone)
732 { $values { "obj" object } { "newobj" "a shallow copy" } }
733 { $description "Outputs a byte-by-byte copy of the given object. User code should call " { $link clone } " instead." } ;
734
735 HELP: declare
736 { $values { "spec" "an array of class words" } }
737 { $description "Declares that the elements at the top of the stack are instances of the classes in " { $snippet "spec" } "." }
738 { $warning "The compiler blindly trusts declarations, and false declarations can lead to crashes, memory corruption and other undesirable behavior." }
739 { $examples
740     "The optimizer cannot do anything with the below code:"
741     { $code "2 + 10 *" }
742     "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:"
743     { $code "{ float } declare 2 + 10 *" }
744 } ;
745
746 HELP: tag
747 { $values { "object" object } { "n" "a tag number" } }
748 { $description "Outputs an object's tag number, between zero and one less than " { $link num-types } ". This is implementation detail and user code should call " { $link class-of } " instead." } ;
749
750 HELP: special-object
751 { $values { "n" "a non-negative integer" } { "obj" object } }
752 { $description "Reads an object from the Factor VM's special object table. User code never has to read the special object table directly; instead, use one of the callers of this word." } ;
753
754 HELP: set-special-object
755 { $values { "obj" object } { "n" "a non-negative integer" } }
756 { $description "Writes an object to the Factor VM's special object table. User code never has to write to the special object table directly; instead, use one of the callers of this word." } ;
757
758 HELP: object
759 { $class-description
760     "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:"
761     { $code "GENERIC: enclose ( number -- array )" "M: number enclose 1array ;" "M: object enclose ;" }
762 } ;
763
764 HELP: null
765 { $class-description
766     "The canonical empty class with no instances."
767 }
768 { $notes
769     "Unlike " { $snippet "null" } " in Java or " { $snippet "NULL" } " in C++, this is not a value signifying empty, or nothing. Use " { $link f } " for this purpose."
770 } ;
771
772 HELP: most
773 { $values { "x" object } { "y" object } { "quot" { $quotation ( x y -- ? ) } } { "z" "either " { $snippet "x" } " or " { $snippet "y" } } }
774 { $description "If the quotation yields a true value when applied to " { $snippet "x" } " and " { $snippet "y" } ", outputs " { $snippet "x" } ", otherwise outputs " { $snippet "y" } "." } ;
775
776 HELP: curry
777 { $values { "obj" object } { "quot" callable } { "curry" curried } }
778 { $description "Partial application. Outputs a " { $link callable } " which first pushes " { $snippet "obj" } " and then calls " { $snippet "quot" } "." }
779 { $notes "Even if " { $snippet "obj" } " is a word, it will be pushed as a literal."
780 $nl
781 "This operation is efficient and does not copy the quotation." }
782 { $examples
783     { $example "USING: kernel prettyprint ;" "5 [ . ] curry ." "[ 5 . ]" }
784     { $example "USING: kernel prettyprint see ;" "\\ = [ see ] curry ." "[ \\ = see ]" }
785     { $example "USING: kernel math prettyprint sequences ;" "{ 1 2 3 } 2 [ - ] curry map ." "{ -1 0 1 }" }
786 } ;
787
788 HELP: curried
789 { $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." } ;
790
791 { curry curried compose prepose composed } related-words
792
793 HELP: 2curry
794 { $values { "obj1" object } { "obj2" object } { "quot" callable } { "curry" curried } }
795 { $description "Outputs a " { $link callable } " which pushes " { $snippet "obj1" } " and " { $snippet "obj2" } " and then calls " { $snippet "quot" } "." }
796 { $notes "This operation is efficient and does not copy the quotation." }
797 { $examples
798     { $example "USING: kernel math prettyprint ;" "5 4 [ + ] 2curry ." "[ 5 4 + ]" }
799 } ;
800
801 HELP: 3curry
802 { $values { "obj1" object } { "obj2" object } { "obj3" object } { "quot" callable } { "curry" curried } }
803 { $description "Outputs a " { $link callable } " which pushes " { $snippet "obj1" } ", " { $snippet "obj2" } " and " { $snippet "obj3" } ", and then calls " { $snippet "quot" } "." }
804 { $notes "This operation is efficient and does not copy the quotation." } ;
805
806 HELP: with
807 { $values { "param" object } { "obj" object } { "quot" { $quotation ( param elt -- ... ) } } { "curry" curried } }
808 { $description "Partial application on the left. The following two lines are equivalent:"
809     { $code "swap [ swap A ] curry B" }
810     { $code "[ A ] with B" }
811
812 }
813 { $notes "This operation is efficient and does not copy the quotation." }
814 { $examples
815     { $example "USING: kernel math prettyprint sequences ;" "1 { 1 2 3 } [ / ] with map ." "{ 1 1/2 1/3 }" }
816     { $example "USING: kernel math prettyprint sequences ;" "1000 100 5 <iota> [ sq + + ] 2with map ." "{ 1100 1101 1104 1109 1116 }" }
817 } ;
818
819 HELP: 2with
820 { $values
821   { "param1" object }
822   { "param2" object }
823   { "obj" object }
824   { "quot" { $quotation ( param1 param2 elt -- ... ) } }
825   { "curry" curried }
826 }
827 { $description "Partial application on the left of two parameters." } ;
828
829 HELP: compose
830 { $values { "quot1" callable } { "quot2" callable } { "compose" composed } }
831 { $description "Quotation composition. Outputs a " { $link callable } " which calls " { $snippet "quot1" } " followed by " { $snippet "quot2" } "." }
832 { $notes
833     "The following two lines are equivalent:"
834     { $code
835         "compose call"
836         "append call"
837     }
838     "However, " { $link compose } " runs in constant time, and the optimizing compiler is able to compile code which calls composed quotations."
839 } ;
840
841 HELP: prepose
842 { $values { "quot1" callable } { "quot2" callable } { "compose" composed } }
843 { $description "Quotation composition. Outputs a " { $link callable } " which calls " { $snippet "quot2" } " followed by " { $snippet "quot1" } "." }
844 { $notes "See " { $link compose } " for details." } ;
845
846 HELP: composed
847 { $class-description "The class of objects created by " { $link compose } ". These objects print identically to quotations and implement the sequence protocol, however they only use two cells of storage; references to the first and second underlying quotations." } ;
848
849 HELP: dip
850 { $values { "x" object } { "quot" quotation } }
851 { $description "Removes " { $snippet "x" } " from the datastack, calls " { $snippet "quot" } ", and restores " { $snippet "x" } " to the top of the datastack when " { $snippet "quot" } " is finished." }
852 { $examples
853     { $example "USING: arrays kernel math prettyprint ;" "10 20 30 [ / ] dip 2array ." "{ 1/2 30 }" }
854 }
855 { $notes { $snippet "dip" } " is executed as a primitive when preceded by a literal quotation. The below definition is not executed unless its argument is a non-literal quotation, such as a quotation constructed with " { $link curry } " or " { $link compose } ", or for " { $link "fry" } " or quotations including " { $link "locals" } "." } ;
856
857 HELP: 2dip
858 { $values { "x" object } { "y" object } { "quot" quotation } }
859 { $description "Removes " { $snippet "x" } " and " { $snippet "y" } " from the datastack, calls " { $snippet "quot" } ", and restores the removed objects to the top of the datastack when " { $snippet "quot" } " is finished." }
860 { $notes "The following are equivalent:"
861     { $code "[ [ foo bar ] dip ] dip" }
862     { $code "[ foo bar ] 2dip" }
863 } ;
864
865 HELP: 3dip
866 { $values { "x" object } { "y" object } { "z" object } { "quot" quotation } }
867 { $description "Removes " { $snippet "x" } ", " { $snippet "y" } ", and " { $snippet "z" } " from the datastack, calls " { $snippet "quot" } ", and restores the removed objects to the top of the datastack when " { $snippet "quot" } " is finished." }
868 { $notes "The following are equivalent:"
869     { $code "[ [ [ foo bar ] dip ] dip ] dip" }
870     { $code "[ foo bar ] 3dip" }
871 } ;
872
873 HELP: 4dip
874 { $values { "w" object } { "x" object } { "y" object } { "z" object } { "quot" quotation } }
875 { $description "Removes " { $snippet "w" } ", " { $snippet "x" } ", " { $snippet "y" } ", and " { $snippet "z" } " from the datastack, calls " { $snippet "quot" } ", and restores the removed objects to the top of the datastack when " { $snippet "quot" } " is finished." }
876 { $notes "The following are equivalent:"
877     { $code "[ [ [ [ foo bar ] dip ] dip ] dip ] dip" }
878     { $code "[ foo bar ] 4dip" }
879 } ;
880
881 HELP: while
882 { $values { "pred" { $quotation ( ..a -- ..b ? ) } } { "body" { $quotation ( ..b -- ..a ) } } }
883 { $description "Calls " { $snippet "body" } " until " { $snippet "pred" } " returns " { $link f } "." } ;
884
885 HELP: until
886 { $values { "pred" { $quotation ( ..a -- ..b ? ) } } { "body" { $quotation ( ..b -- ..a ) } } }
887 { $description "Calls " { $snippet "body" } " until " { $snippet "pred" } " returns " { $link t } "." } ;
888
889 HELP: do
890 { $values { "pred" { $quotation ( ..a -- ..b ? ) } } { "body" { $quotation ( ..b -- ..a ) } } }
891 { $description "Executes one iteration of a " { $link while } " or " { $link until } " loop." } ;
892
893 HELP: loop
894 { $values
895      { "pred" quotation } }
896      { $description "Calls the quotation repeatedly until it outputs " { $link f } "." }
897 { $examples "Loop until we hit a zero:"
898     { $unchecked-example "USING: kernel random math io ; "
899     " [ \"hi\" write bl 10 random zero? not ] loop"
900     "hi hi hi" }
901     "A fun loop:"
902     { $example "USING: kernel prettyprint math ; "
903     "3 [ dup . 7 + 11 mod dup 3 = not ] loop drop"
904     "3\n10\n6\n2\n9\n5\n1\n8\n4\n0\n7" }
905 } ;
906
907 ARTICLE: "looping-combinators" "Looping combinators"
908 "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."
909 { $subsections
910     while
911     until
912 }
913 "To execute one iteration of a loop, use the following word:"
914 { $subsections do }
915 "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 } ":"
916 { $code
917     "[ P ] [ Q ] do while"
918 }
919 "A simpler looping combinator which executes a single quotation until it returns " { $link f } ":"
920 { $subsections loop } ;
921
922 HELP: assert
923 { $values { "got" "the obtained value" } { "expect" "the expected value" } }
924 { $description "Throws an " { $link assert } " error." }
925 { $error-description "Thrown when a unit test or other assertion fails." } ;
926
927 HELP: assert=
928 { $values { "a" object } { "b" object } }
929 { $description "Throws an " { $link assert } " error if " { $snippet "a" } " does not equal " { $snippet "b" } "." } ;
930
931 HELP: become
932 { $values { "old" array } { "new" array } }
933 { $description "Replaces all references to objects in " { $snippet "old" } " with the corresponding object in " { $snippet "new" } ". This word is used to implement tuple reshaping. See " { $link "tuple-redefinition" } "." } ;
934
935 ARTICLE: "shuffle-words-complex" "Complex shuffle words"
936 "These shuffle words tend to make code difficult to read and to reason about. Code that uses them should almost always be rewritten using " { $link "locals" } " or " { $link "dataflow-combinators" } "."
937 $nl
938 "Duplicating stack elements deep in the stack:"
939 { $subsections
940     dupd
941 }
942 "Permuting stack elements deep in the stack:"
943 { $subsections
944     swapd
945     rot
946     -rot
947 } ;
948
949 ARTICLE: "callables" "Callables"
950 "Aside from " { $link "quotations" } ", there are two other callables that efficiently combine computations."
951 $nl
952 "Currying an object onto a quotation:"
953 { $subsections
954     curry
955     curried
956 }
957 "Composing two quotations:"
958 { $subsections
959     compose
960     composed
961 } ;
962
963 ARTICLE: "shuffle-words" "Shuffle words"
964 "Shuffle words rearrange items at the top of the data stack as indicated by their stack effects. They provide simple data flow control between words. More complex data flow control is available with the " { $link "dataflow-combinators" } " and with " { $link "locals" } "."
965 $nl
966 "Removing stack elements:"
967 { $subsections
968     drop
969     2drop
970     3drop
971     nip
972     2nip
973 }
974 "Duplicating stack elements:"
975 { $subsections
976     dup
977     2dup
978     3dup
979     over
980     2over
981     pick
982 }
983 "Permuting stack elements:"
984 { $subsections
985     swap
986 }
987 "There are additional, more complex stack shuffling words whose use is not recommended."
988 { $subsections
989     "shuffle-words-complex"
990 } ;
991
992 ARTICLE: "equality" "Equality"
993 "There are two distinct notions of “sameness” when it comes to objects."
994 $nl
995 "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:"
996 { $subsections eq? }
997 "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" } "):"
998 { $subsections = }
999 "A third form of equality is provided by " { $link number= } ". It compares numeric value while disregarding types."
1000 $nl
1001 "Custom value comparison methods for use with " { $link = } " can be defined on a generic word:"
1002 { $subsections equal? }
1003 "Utility class:"
1004 { $subsections identity-tuple }
1005 "An object can be cloned; the clone has distinct identity but equal value:"
1006 { $subsections clone } ;
1007
1008 ARTICLE: "assertions" "Assertions"
1009 "Some words to make assertions easier to enforce:"
1010 { $subsections
1011     assert
1012     assert=
1013 } ;