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