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