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