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