/core/kernel/kernel-docs.factor

http://github.com/abeaumont/factor · Factor · 956 lines · 854 code · 102 blank · 0 comment · 45 complexity · 4123d14eb5b39146a7af22c290b21984 MD5 · raw file

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