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