@rcrsr/rill 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +187 -0
  3. package/dist/cli.d.ts +11 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +69 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/demo.d.ts +6 -0
  8. package/dist/demo.d.ts.map +1 -0
  9. package/dist/demo.js +121 -0
  10. package/dist/demo.js.map +1 -0
  11. package/dist/index.d.ts +10 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +9 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/lexer/errors.d.ts +9 -0
  16. package/dist/lexer/errors.d.ts.map +1 -0
  17. package/dist/lexer/errors.js +12 -0
  18. package/dist/lexer/errors.js.map +1 -0
  19. package/dist/lexer/helpers.d.ts +14 -0
  20. package/dist/lexer/helpers.d.ts.map +1 -0
  21. package/dist/lexer/helpers.js +30 -0
  22. package/dist/lexer/helpers.js.map +1 -0
  23. package/dist/lexer/index.d.ts +8 -0
  24. package/dist/lexer/index.d.ts.map +1 -0
  25. package/dist/lexer/index.js +8 -0
  26. package/dist/lexer/index.js.map +1 -0
  27. package/dist/lexer/operators.d.ts +11 -0
  28. package/dist/lexer/operators.d.ts.map +1 -0
  29. package/dist/lexer/operators.js +58 -0
  30. package/dist/lexer/operators.js.map +1 -0
  31. package/dist/lexer/readers.d.ts +12 -0
  32. package/dist/lexer/readers.d.ts.map +1 -0
  33. package/dist/lexer/readers.js +144 -0
  34. package/dist/lexer/readers.js.map +1 -0
  35. package/dist/lexer/state.d.ts +18 -0
  36. package/dist/lexer/state.d.ts.map +1 -0
  37. package/dist/lexer/state.js +37 -0
  38. package/dist/lexer/state.js.map +1 -0
  39. package/dist/lexer/tokenizer.d.ts +9 -0
  40. package/dist/lexer/tokenizer.d.ts.map +1 -0
  41. package/dist/lexer/tokenizer.js +100 -0
  42. package/dist/lexer/tokenizer.js.map +1 -0
  43. package/dist/lexer.d.ts +19 -0
  44. package/dist/lexer.d.ts.map +1 -0
  45. package/dist/lexer.js +344 -0
  46. package/dist/lexer.js.map +1 -0
  47. package/dist/parser/arithmetic.d.ts +16 -0
  48. package/dist/parser/arithmetic.d.ts.map +1 -0
  49. package/dist/parser/arithmetic.js +128 -0
  50. package/dist/parser/arithmetic.js.map +1 -0
  51. package/dist/parser/boolean.d.ts +15 -0
  52. package/dist/parser/boolean.d.ts.map +1 -0
  53. package/dist/parser/boolean.js +20 -0
  54. package/dist/parser/boolean.js.map +1 -0
  55. package/dist/parser/control-flow.d.ts +56 -0
  56. package/dist/parser/control-flow.d.ts.map +1 -0
  57. package/dist/parser/control-flow.js +167 -0
  58. package/dist/parser/control-flow.js.map +1 -0
  59. package/dist/parser/expressions.d.ts +23 -0
  60. package/dist/parser/expressions.d.ts.map +1 -0
  61. package/dist/parser/expressions.js +950 -0
  62. package/dist/parser/expressions.js.map +1 -0
  63. package/dist/parser/extraction.d.ts +48 -0
  64. package/dist/parser/extraction.d.ts.map +1 -0
  65. package/dist/parser/extraction.js +279 -0
  66. package/dist/parser/extraction.js.map +1 -0
  67. package/dist/parser/functions.d.ts +20 -0
  68. package/dist/parser/functions.d.ts.map +1 -0
  69. package/dist/parser/functions.js +96 -0
  70. package/dist/parser/functions.js.map +1 -0
  71. package/dist/parser/helpers.d.ts +94 -0
  72. package/dist/parser/helpers.d.ts.map +1 -0
  73. package/dist/parser/helpers.js +225 -0
  74. package/dist/parser/helpers.js.map +1 -0
  75. package/dist/parser/index.d.ts +49 -0
  76. package/dist/parser/index.d.ts.map +1 -0
  77. package/dist/parser/index.js +73 -0
  78. package/dist/parser/index.js.map +1 -0
  79. package/dist/parser/literals.d.ts +37 -0
  80. package/dist/parser/literals.d.ts.map +1 -0
  81. package/dist/parser/literals.js +373 -0
  82. package/dist/parser/literals.js.map +1 -0
  83. package/dist/parser/parser-collect.d.ts +16 -0
  84. package/dist/parser/parser-collect.d.ts.map +1 -0
  85. package/dist/parser/parser-collect.js +125 -0
  86. package/dist/parser/parser-collect.js.map +1 -0
  87. package/dist/parser/parser-control.d.ts +20 -0
  88. package/dist/parser/parser-control.d.ts.map +1 -0
  89. package/dist/parser/parser-control.js +120 -0
  90. package/dist/parser/parser-control.js.map +1 -0
  91. package/dist/parser/parser-expr.d.ts +37 -0
  92. package/dist/parser/parser-expr.d.ts.map +1 -0
  93. package/dist/parser/parser-expr.js +639 -0
  94. package/dist/parser/parser-expr.js.map +1 -0
  95. package/dist/parser/parser-extract.d.ts +17 -0
  96. package/dist/parser/parser-extract.d.ts.map +1 -0
  97. package/dist/parser/parser-extract.js +222 -0
  98. package/dist/parser/parser-extract.js.map +1 -0
  99. package/dist/parser/parser-functions.d.ts +21 -0
  100. package/dist/parser/parser-functions.d.ts.map +1 -0
  101. package/dist/parser/parser-functions.js +155 -0
  102. package/dist/parser/parser-functions.js.map +1 -0
  103. package/dist/parser/parser-literals.d.ts +22 -0
  104. package/dist/parser/parser-literals.d.ts.map +1 -0
  105. package/dist/parser/parser-literals.js +288 -0
  106. package/dist/parser/parser-literals.js.map +1 -0
  107. package/dist/parser/parser-script.d.ts +21 -0
  108. package/dist/parser/parser-script.d.ts.map +1 -0
  109. package/dist/parser/parser-script.js +174 -0
  110. package/dist/parser/parser-script.js.map +1 -0
  111. package/dist/parser/parser-variables.d.ts +20 -0
  112. package/dist/parser/parser-variables.d.ts.map +1 -0
  113. package/dist/parser/parser-variables.js +146 -0
  114. package/dist/parser/parser-variables.js.map +1 -0
  115. package/dist/parser/parser.d.ts +49 -0
  116. package/dist/parser/parser.d.ts.map +1 -0
  117. package/dist/parser/parser.js +54 -0
  118. package/dist/parser/parser.js.map +1 -0
  119. package/dist/parser/script.d.ts +14 -0
  120. package/dist/parser/script.d.ts.map +1 -0
  121. package/dist/parser/script.js +196 -0
  122. package/dist/parser/script.js.map +1 -0
  123. package/dist/parser/state.d.ts +40 -0
  124. package/dist/parser/state.d.ts.map +1 -0
  125. package/dist/parser/state.js +129 -0
  126. package/dist/parser/state.js.map +1 -0
  127. package/dist/parser/variables.d.ts +10 -0
  128. package/dist/parser/variables.d.ts.map +1 -0
  129. package/dist/parser/variables.js +215 -0
  130. package/dist/parser/variables.js.map +1 -0
  131. package/dist/runtime/ast-equals.d.ts +13 -0
  132. package/dist/runtime/ast-equals.d.ts.map +1 -0
  133. package/dist/runtime/ast-equals.js +447 -0
  134. package/dist/runtime/ast-equals.js.map +1 -0
  135. package/dist/runtime/builtins.d.ts +13 -0
  136. package/dist/runtime/builtins.d.ts.map +1 -0
  137. package/dist/runtime/builtins.js +180 -0
  138. package/dist/runtime/builtins.js.map +1 -0
  139. package/dist/runtime/callable.d.ts +88 -0
  140. package/dist/runtime/callable.d.ts.map +1 -0
  141. package/dist/runtime/callable.js +98 -0
  142. package/dist/runtime/callable.js.map +1 -0
  143. package/dist/runtime/context.d.ts +13 -0
  144. package/dist/runtime/context.d.ts.map +1 -0
  145. package/dist/runtime/context.js +73 -0
  146. package/dist/runtime/context.js.map +1 -0
  147. package/dist/runtime/core/callable.d.ts +171 -0
  148. package/dist/runtime/core/callable.d.ts.map +1 -0
  149. package/dist/runtime/core/callable.js +246 -0
  150. package/dist/runtime/core/callable.js.map +1 -0
  151. package/dist/runtime/core/context.d.ts +29 -0
  152. package/dist/runtime/core/context.d.ts.map +1 -0
  153. package/dist/runtime/core/context.js +154 -0
  154. package/dist/runtime/core/context.js.map +1 -0
  155. package/dist/runtime/core/equals.d.ts +9 -0
  156. package/dist/runtime/core/equals.d.ts.map +1 -0
  157. package/dist/runtime/core/equals.js +381 -0
  158. package/dist/runtime/core/equals.js.map +1 -0
  159. package/dist/runtime/core/eval/base.d.ts +65 -0
  160. package/dist/runtime/core/eval/base.d.ts.map +1 -0
  161. package/dist/runtime/core/eval/base.js +112 -0
  162. package/dist/runtime/core/eval/base.js.map +1 -0
  163. package/dist/runtime/core/eval/evaluator.d.ts +47 -0
  164. package/dist/runtime/core/eval/evaluator.d.ts.map +1 -0
  165. package/dist/runtime/core/eval/evaluator.js +73 -0
  166. package/dist/runtime/core/eval/evaluator.js.map +1 -0
  167. package/dist/runtime/core/eval/index.d.ts +57 -0
  168. package/dist/runtime/core/eval/index.d.ts.map +1 -0
  169. package/dist/runtime/core/eval/index.js +95 -0
  170. package/dist/runtime/core/eval/index.js.map +1 -0
  171. package/dist/runtime/core/eval/mixins/annotations.d.ts +19 -0
  172. package/dist/runtime/core/eval/mixins/annotations.d.ts.map +1 -0
  173. package/dist/runtime/core/eval/mixins/annotations.js +146 -0
  174. package/dist/runtime/core/eval/mixins/annotations.js.map +1 -0
  175. package/dist/runtime/core/eval/mixins/closures.d.ts +49 -0
  176. package/dist/runtime/core/eval/mixins/closures.d.ts.map +1 -0
  177. package/dist/runtime/core/eval/mixins/closures.js +479 -0
  178. package/dist/runtime/core/eval/mixins/closures.js.map +1 -0
  179. package/dist/runtime/core/eval/mixins/collections.d.ts +24 -0
  180. package/dist/runtime/core/eval/mixins/collections.d.ts.map +1 -0
  181. package/dist/runtime/core/eval/mixins/collections.js +466 -0
  182. package/dist/runtime/core/eval/mixins/collections.js.map +1 -0
  183. package/dist/runtime/core/eval/mixins/control-flow.d.ts +27 -0
  184. package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +1 -0
  185. package/dist/runtime/core/eval/mixins/control-flow.js +369 -0
  186. package/dist/runtime/core/eval/mixins/control-flow.js.map +1 -0
  187. package/dist/runtime/core/eval/mixins/core.d.ts +24 -0
  188. package/dist/runtime/core/eval/mixins/core.d.ts.map +1 -0
  189. package/dist/runtime/core/eval/mixins/core.js +335 -0
  190. package/dist/runtime/core/eval/mixins/core.js.map +1 -0
  191. package/dist/runtime/core/eval/mixins/expressions.d.ts +19 -0
  192. package/dist/runtime/core/eval/mixins/expressions.d.ts.map +1 -0
  193. package/dist/runtime/core/eval/mixins/expressions.js +202 -0
  194. package/dist/runtime/core/eval/mixins/expressions.js.map +1 -0
  195. package/dist/runtime/core/eval/mixins/extraction.d.ts +10 -0
  196. package/dist/runtime/core/eval/mixins/extraction.d.ts.map +1 -0
  197. package/dist/runtime/core/eval/mixins/extraction.js +250 -0
  198. package/dist/runtime/core/eval/mixins/extraction.js.map +1 -0
  199. package/dist/runtime/core/eval/mixins/literals.d.ts +23 -0
  200. package/dist/runtime/core/eval/mixins/literals.d.ts.map +1 -0
  201. package/dist/runtime/core/eval/mixins/literals.js +180 -0
  202. package/dist/runtime/core/eval/mixins/literals.js.map +1 -0
  203. package/dist/runtime/core/eval/mixins/types.d.ts +20 -0
  204. package/dist/runtime/core/eval/mixins/types.d.ts.map +1 -0
  205. package/dist/runtime/core/eval/mixins/types.js +109 -0
  206. package/dist/runtime/core/eval/mixins/types.js.map +1 -0
  207. package/dist/runtime/core/eval/mixins/variables.d.ts +34 -0
  208. package/dist/runtime/core/eval/mixins/variables.d.ts.map +1 -0
  209. package/dist/runtime/core/eval/mixins/variables.js +247 -0
  210. package/dist/runtime/core/eval/mixins/variables.js.map +1 -0
  211. package/dist/runtime/core/eval/types.d.ts +41 -0
  212. package/dist/runtime/core/eval/types.d.ts.map +1 -0
  213. package/dist/runtime/core/eval/types.js +10 -0
  214. package/dist/runtime/core/eval/types.js.map +1 -0
  215. package/dist/runtime/core/evaluate.d.ts +42 -0
  216. package/dist/runtime/core/evaluate.d.ts.map +1 -0
  217. package/dist/runtime/core/evaluate.debug.js +1251 -0
  218. package/dist/runtime/core/evaluate.js +1913 -0
  219. package/dist/runtime/core/evaluate.js.map +1 -0
  220. package/dist/runtime/core/execute.d.ts +26 -0
  221. package/dist/runtime/core/execute.d.ts.map +1 -0
  222. package/dist/runtime/core/execute.js +177 -0
  223. package/dist/runtime/core/execute.js.map +1 -0
  224. package/dist/runtime/core/signals.d.ts +19 -0
  225. package/dist/runtime/core/signals.d.ts.map +1 -0
  226. package/dist/runtime/core/signals.js +26 -0
  227. package/dist/runtime/core/signals.js.map +1 -0
  228. package/dist/runtime/core/types.d.ts +177 -0
  229. package/dist/runtime/core/types.d.ts.map +1 -0
  230. package/dist/runtime/core/types.js +50 -0
  231. package/dist/runtime/core/types.js.map +1 -0
  232. package/dist/runtime/core/values.d.ts +66 -0
  233. package/dist/runtime/core/values.d.ts.map +1 -0
  234. package/dist/runtime/core/values.js +240 -0
  235. package/dist/runtime/core/values.js.map +1 -0
  236. package/dist/runtime/evaluate.d.ts +32 -0
  237. package/dist/runtime/evaluate.d.ts.map +1 -0
  238. package/dist/runtime/evaluate.js +1111 -0
  239. package/dist/runtime/evaluate.js.map +1 -0
  240. package/dist/runtime/execute.d.ts +26 -0
  241. package/dist/runtime/execute.d.ts.map +1 -0
  242. package/dist/runtime/execute.js +121 -0
  243. package/dist/runtime/execute.js.map +1 -0
  244. package/dist/runtime/ext/builtins.d.ts +16 -0
  245. package/dist/runtime/ext/builtins.d.ts.map +1 -0
  246. package/dist/runtime/ext/builtins.js +528 -0
  247. package/dist/runtime/ext/builtins.js.map +1 -0
  248. package/dist/runtime/ext/content-parser.d.ts +83 -0
  249. package/dist/runtime/ext/content-parser.d.ts.map +1 -0
  250. package/dist/runtime/ext/content-parser.js +536 -0
  251. package/dist/runtime/ext/content-parser.js.map +1 -0
  252. package/dist/runtime/index.d.ts +28 -0
  253. package/dist/runtime/index.d.ts.map +1 -0
  254. package/dist/runtime/index.js +34 -0
  255. package/dist/runtime/index.js.map +1 -0
  256. package/dist/runtime/signals.d.ts +19 -0
  257. package/dist/runtime/signals.d.ts.map +1 -0
  258. package/dist/runtime/signals.js +26 -0
  259. package/dist/runtime/signals.js.map +1 -0
  260. package/dist/runtime/types.d.ts +169 -0
  261. package/dist/runtime/types.d.ts.map +1 -0
  262. package/dist/runtime/types.js +50 -0
  263. package/dist/runtime/types.js.map +1 -0
  264. package/dist/runtime/values.d.ts +50 -0
  265. package/dist/runtime/values.d.ts.map +1 -0
  266. package/dist/runtime/values.js +209 -0
  267. package/dist/runtime/values.js.map +1 -0
  268. package/dist/runtime.d.ts +254 -0
  269. package/dist/runtime.d.ts.map +1 -0
  270. package/dist/runtime.js +2014 -0
  271. package/dist/runtime.js.map +1 -0
  272. package/dist/types.d.ts +752 -0
  273. package/dist/types.d.ts.map +1 -0
  274. package/dist/types.js +189 -0
  275. package/dist/types.js.map +1 -0
  276. package/docs/00_INDEX.md +65 -0
  277. package/docs/01_guide.md +390 -0
  278. package/docs/02_types.md +399 -0
  279. package/docs/03_variables.md +314 -0
  280. package/docs/04_operators.md +551 -0
  281. package/docs/05_control-flow.md +350 -0
  282. package/docs/06_closures.md +353 -0
  283. package/docs/07_collections.md +686 -0
  284. package/docs/08_iterators.md +330 -0
  285. package/docs/09_strings.md +205 -0
  286. package/docs/10_parsing.md +366 -0
  287. package/docs/11_reference.md +350 -0
  288. package/docs/12_examples.md +771 -0
  289. package/docs/13_modules.md +519 -0
  290. package/docs/14_host-integration.md +826 -0
  291. package/docs/15_grammar.ebnf +693 -0
  292. package/docs/16_conventions.md +696 -0
  293. package/docs/99_llm-reference.txt +300 -0
  294. package/docs/assets/logo.png +0 -0
  295. package/package.json +70 -0
@@ -0,0 +1,686 @@
1
+ # rill Collection Operators
2
+
3
+ *Sequential and parallel iteration with each, map, filter, and fold*
4
+
5
+ ## Overview
6
+
7
+ rill provides four collection operators for transforming, filtering, and reducing data:
8
+
9
+ | Operator | Execution | Accumulator | Returns |
10
+ |----------|-----------|-------------|---------|
11
+ | `each` | Sequential | Optional | List of all results |
12
+ | `map` | Parallel | No | List of all results |
13
+ | `filter` | Parallel | No | Elements where predicate is true |
14
+ | `fold` | Sequential | Required | Final result only |
15
+
16
+ All three operators share similar syntax but differ in execution model and output.
17
+
18
+ ```rill
19
+ # Sequential: results in order, one at a time
20
+ [1, 2, 3] -> each { $ * 2 } # [2, 4, 6]
21
+
22
+ # Parallel: results in order, concurrent execution
23
+ [1, 2, 3] -> map { $ * 2 } # [2, 4, 6]
24
+
25
+ # Parallel filter: keep matching elements
26
+ [1, 2, 3, 4, 5] -> filter { $ > 2 } # [3, 4, 5]
27
+
28
+ # Reduction: accumulates to single value
29
+ [1, 2, 3] -> fold(0) { $@ + $ } # 6
30
+ ```
31
+
32
+ ## Body Forms
33
+
34
+ Each operator accepts multiple body syntaxes. Choose based on readability and complexity.
35
+
36
+ | Form | Syntax | When to Use |
37
+ |------|--------|-------------|
38
+ | Block | `{ body }` | Multi-statement logic; `$` is current element |
39
+ | Grouped | `( expr )` | Single expression; `$` is current element |
40
+ | Inline closure | `\|x\| body` | Named parameters; reusable logic |
41
+ | Variable | `$fn` | Pre-defined closure; maximum reuse |
42
+ | Identity | `$` | Return elements unchanged |
43
+ | Method | `.method` | Apply method to each element |
44
+
45
+ ### Block Form
46
+
47
+ Use braces for multi-statement bodies. `$` refers to the current element.
48
+
49
+ ```rill
50
+ [1, 2, 3] -> each {
51
+ $ :> $x
52
+ $x * 2
53
+ }
54
+ # Result: [2, 4, 6]
55
+ ```
56
+
57
+ ### Grouped Expression
58
+
59
+ Use parentheses for single expressions. `$` refers to the current element.
60
+
61
+ ```rill
62
+ [1, 2, 3] -> each ($ + 10)
63
+ # Result: [11, 12, 13]
64
+ ```
65
+
66
+ ### Inline Closure
67
+
68
+ Define parameters explicitly. The first parameter receives each element.
69
+
70
+ ```rill
71
+ [1, 2, 3] -> each |x| ($x * 2)
72
+ # Result: [2, 4, 6]
73
+ ```
74
+
75
+ ### Variable Closure
76
+
77
+ Reference a pre-defined closure by variable.
78
+
79
+ ```rill
80
+ |x| ($x * 2) :> $double
81
+ [1, 2, 3] -> each $double
82
+ # Result: [2, 4, 6]
83
+ ```
84
+
85
+ ### Identity
86
+
87
+ Use bare `$` to return elements unchanged.
88
+
89
+ ```rill
90
+ [1, 2, 3] -> each $
91
+ # Result: [1, 2, 3]
92
+ ```
93
+
94
+ ### Method Shorthand
95
+
96
+ Use `.method` to apply a method to each element. Equivalent to `{ $.method() }`.
97
+
98
+ ```rill
99
+ ["hello", "world"] -> each .upper
100
+ # Result: ["HELLO", "WORLD"]
101
+
102
+ [" hi ", " there "] -> map .trim
103
+ # Result: ["hi", "there"]
104
+
105
+ ["hello", "", "world"] -> filter .empty
106
+ # Result: [""]
107
+ ```
108
+
109
+ Methods can take arguments:
110
+
111
+ ```rill
112
+ ["a", "b"] -> map .pad_start(3, "0")
113
+ # Result: ["00a", "00b"]
114
+ ```
115
+
116
+ Chain multiple methods:
117
+
118
+ ```rill
119
+ [" HELLO ", " WORLD "] -> map .trim.lower
120
+ # Result: ["hello", "world"]
121
+ ```
122
+
123
+ For negation, use grouped expression:
124
+
125
+ ```rill
126
+ ["hello", "", "world"] -> filter (!.empty)
127
+ # Result: ["hello", "world"]
128
+ ```
129
+
130
+ ---
131
+
132
+ ## each — Sequential Iteration
133
+
134
+ `each` iterates over a collection in order. Each iteration completes before the next begins.
135
+
136
+ ```rill
137
+ collection -> each body
138
+ collection -> each (init) body # with accumulator
139
+ ```
140
+
141
+ ### Basic Usage
142
+
143
+ ```rill
144
+ # Double each number
145
+ [1, 2, 3] -> each { $ * 2 }
146
+ # Result: [2, 4, 6]
147
+
148
+ # Transform strings
149
+ ["a", "b", "c"] -> each { "{$}!" }
150
+ # Result: ["a!", "b!", "c!"]
151
+
152
+ # Iterate string characters
153
+ "hello" -> each $
154
+ # Result: ["h", "e", "l", "l", "o"]
155
+ ```
156
+
157
+ ### Dict Iteration
158
+
159
+ When iterating over a dict, `$` contains `key` and `value` fields.
160
+
161
+ ```rill
162
+ [name: "alice", age: 30] -> each { "{$.key}: {$.value}" }
163
+ # Result: ["name: alice", "age: 30"]
164
+
165
+ [a: 1, b: 2, c: 3] -> each { $.value * 2 }
166
+ # Result: [2, 4, 6]
167
+ ```
168
+
169
+ ### With Accumulator
170
+
171
+ `each` supports an optional accumulator for stateful iteration. Two syntaxes exist.
172
+
173
+ #### Block Form with `$@`
174
+
175
+ Place initial value in parentheses before the block. Access accumulator via `$@`.
176
+
177
+ ```rill
178
+ # Running sum (scan pattern)
179
+ [1, 2, 3] -> each(0) { $@ + $ }
180
+ # Result: [1, 3, 6]
181
+
182
+ # String concatenation
183
+ ["a", "b", "c"] -> each("") { "{$@}{$}" }
184
+ # Result: ["a", "ab", "abc"]
185
+ ```
186
+
187
+ #### Inline Closure Form
188
+
189
+ Define accumulator as the last parameter with a default value.
190
+
191
+ ```rill
192
+ # Running sum
193
+ [1, 2, 3] -> each |x, acc = 0| ($acc + $x)
194
+ # Result: [1, 3, 6]
195
+ ```
196
+
197
+ ### Early Termination
198
+
199
+ Use `break` to exit `each` early. Returns partial results collected before the break.
200
+
201
+ ```rill
202
+ [1, 2, 3, 4, 5] -> each {
203
+ ($ == 3) ? break
204
+ $ * 2
205
+ }
206
+ # Result: [2, 4] (partial results before break)
207
+ ```
208
+
209
+ ### Empty Collections
210
+
211
+ `each` returns `[]` for empty collections. The body never executes.
212
+
213
+ ```rill
214
+ [] -> each { $ * 2 }
215
+ # Result: []
216
+
217
+ # With accumulator, still returns [] (not the initial value)
218
+ [] -> each(0) { $@ + $ }
219
+ # Result: []
220
+ ```
221
+
222
+ ---
223
+
224
+ ## map — Parallel Iteration
225
+
226
+ `map` iterates concurrently using `Promise.all`. Order is preserved despite parallel execution.
227
+
228
+ ```rill
229
+ collection -> map body
230
+ ```
231
+
232
+ ### Basic Usage
233
+
234
+ ```rill
235
+ # Map with closure parameter
236
+ ["a", "b", "c"] -> map |x| { "{$x}!" }
237
+ # Result: ["a!", "b!", "c!"]
238
+
239
+ # Block expression (implicit $)
240
+ [1, 2, 3] -> map { $ * 2 }
241
+ # Result: [2, 4, 6]
242
+
243
+ # Grouped expression
244
+ [1, 2, 3] -> map ($ * 2)
245
+ # Result: [2, 4, 6]
246
+ ```
247
+
248
+ ### Key Differences from each
249
+
250
+ 1. **No accumulator**: Parallel execution has no "previous" value
251
+ 2. **No break**: Cannot exit early from concurrent operations
252
+ 3. **Concurrent execution**: All iterations start immediately
253
+
254
+ ### When to Use map
255
+
256
+ Use `map` when:
257
+ - Operations are independent (no shared state)
258
+ - Order of execution doesn't matter (results still ordered)
259
+ - I/O-bound operations benefit from concurrency
260
+
261
+ ```rill
262
+ # Fetch pages concurrently (faster than sequential)
263
+ ["page1", "page2", "page3"] -> map |id| fetch_page($id)
264
+
265
+ # CPU-bound: same result as each, but runs in parallel
266
+ [1, 2, 3, 4, 5] -> map { $ * $ }
267
+ # Result: [1, 4, 9, 16, 25]
268
+ ```
269
+
270
+ ### Empty Collections
271
+
272
+ `map` returns `[]` for empty collections. The body never executes.
273
+
274
+ ```rill
275
+ [] -> map { $ * 2 }
276
+ # Result: []
277
+ ```
278
+
279
+ ---
280
+
281
+ ## filter — Parallel Filtering
282
+
283
+ `filter` keeps elements where the predicate returns `true`. Predicates must return boolean values. Executes concurrently using `Promise.all`.
284
+
285
+ ```rill
286
+ collection -> filter body
287
+ ```
288
+
289
+ ### Basic Usage
290
+
291
+ ```rill
292
+ # Keep numbers greater than 2
293
+ [1, 2, 3, 4, 5] -> filter { $ > 2 }
294
+ # Result: [3, 4, 5]
295
+
296
+ # Keep non-empty strings
297
+ ["hello", "", "world", ""] -> filter { !.empty }
298
+ # Result: ["hello", "world"]
299
+
300
+ # Keep even numbers
301
+ [1, 2, 3, 4, 5, 6] -> filter { ($ % 2) == 0 }
302
+ # Result: [2, 4, 6]
303
+ ```
304
+
305
+ ### All Body Forms
306
+
307
+ `filter` accepts the same body forms as `map`:
308
+
309
+ ```rill
310
+ # Block form
311
+ [1, 2, 3, 4, 5] -> filter { $ > 2 }
312
+
313
+ # Grouped expression
314
+ [1, 2, 3, 4, 5] -> filter ($ > 2)
315
+
316
+ # Inline closure
317
+ [1, 2, 3, 4, 5] -> filter |x| ($x > 2)
318
+
319
+ # Variable closure
320
+ |x| ($x > 2) :> $gtTwo
321
+ [1, 2, 3, 4, 5] -> filter $gtTwo
322
+ ```
323
+
324
+ ### Dict Filtering
325
+
326
+ When filtering a dict, `$` contains `key` and `value` fields. Returns list of matching entries.
327
+
328
+ ```rill
329
+ [a: 1, b: 5, c: 3] -> filter { $.value > 2 }
330
+ # Result: [{ key: "b", value: 5 }, { key: "c", value: 3 }]
331
+ ```
332
+
333
+ ### String Filtering
334
+
335
+ Filters characters in a string.
336
+
337
+ ```rill
338
+ "hello" -> filter { $ != "l" }
339
+ # Result: ["h", "e", "o"]
340
+ ```
341
+
342
+ ### Chaining with Other Operators
343
+
344
+ ```rill
345
+ # Filter then transform
346
+ [1, 2, 3, 4, 5] -> filter { $ > 2 } -> map { $ * 2 }
347
+ # Result: [6, 8, 10]
348
+
349
+ # Transform then filter
350
+ [1, 2, 3, 4, 5] -> map { $ * 2 } -> filter { $ > 5 }
351
+ # Result: [6, 8, 10]
352
+
353
+ # Filter, transform, reduce
354
+ [1, 2, 3, 4, 5] -> filter { $ > 2 } -> map { $ * 2 } -> fold(0) { $@ + $ }
355
+ # Result: 24
356
+ ```
357
+
358
+ ### Empty Collections
359
+
360
+ `filter` returns `[]` for empty collections or when nothing matches.
361
+
362
+ ```rill
363
+ [] -> filter { $ > 0 }
364
+ # Result: []
365
+
366
+ [1, 2, 3] -> filter { $ > 10 }
367
+ # Result: []
368
+ ```
369
+
370
+ ---
371
+
372
+ ## fold — Sequential Reduction
373
+
374
+ `fold` reduces a collection to a single value. Requires an accumulator.
375
+
376
+ Syntax forms:
377
+ - Block form: `collection -> fold(init) { body }`
378
+ - Closure form: `collection -> fold |x, acc = init| (body)`
379
+ - Variable closure: `collection -> fold $fn`
380
+
381
+ ### Basic Usage
382
+
383
+ ```rill
384
+ # Sum numbers
385
+ [1, 2, 3] -> fold(0) { $@ + $ }
386
+ # Result: 6
387
+
388
+ # Same with inline closure
389
+ [1, 2, 3] -> fold |x, sum = 0| ($sum + $x)
390
+ # Result: 6
391
+ ```
392
+
393
+ ### Common Patterns
394
+
395
+ #### Sum
396
+
397
+ ```rill
398
+ [1, 2, 3, 4, 5] -> fold(0) { $@ + $ }
399
+ # Result: 15
400
+ ```
401
+
402
+ #### Product
403
+
404
+ ```rill
405
+ [1, 2, 3, 4] -> fold(1) { $@ * $ }
406
+ # Result: 24
407
+ ```
408
+
409
+ #### Maximum
410
+
411
+ ```rill
412
+ [3, 1, 4, 1, 5, 9] -> fold(0) {
413
+ ($@ > $) ? $@ ! $
414
+ }
415
+ # Result: 9
416
+ ```
417
+
418
+ #### Count
419
+
420
+ ```rill
421
+ [1, 2, 3, 4, 5] -> fold(0) { $@ + 1 }
422
+ # Result: 5
423
+ ```
424
+
425
+ #### String Join
426
+
427
+ ```rill
428
+ ["a", "b", "c"] -> fold("") { "{$@}{$}" }
429
+ # Result: "abc"
430
+
431
+ # With separator
432
+ ["a", "b", "c"] -> fold |x, acc = ""| {
433
+ ($acc -> .empty) ? $x ! "{$acc},{$x}"
434
+ }
435
+ # Result: "a,b,c"
436
+ ```
437
+
438
+ ### Dict Reduction
439
+
440
+ When folding over a dict, `$` contains `key` and `value` fields.
441
+
442
+ ```rill
443
+ [a: 1, b: 2, c: 3] -> fold |entry, sum = 0| ($sum + $entry.value)
444
+ # Result: 6
445
+ ```
446
+
447
+ ### Reusable Reducers
448
+
449
+ Define closures for common reductions.
450
+
451
+ ```rill
452
+ # Define reusable reducers
453
+ |x, sum = 0| ($sum + $x) :> $summer
454
+ |x, max = 0| (($x > $max) ? $x ! $max) :> $maxer
455
+
456
+ # Use with different data
457
+ [1, 2, 3] -> fold $summer # 6
458
+ [3, 7, 2] -> fold $maxer # 7
459
+ [9, 1, 5] -> fold $maxer # 9
460
+ ```
461
+
462
+ ### Empty Collections
463
+
464
+ `fold` returns the initial value for empty collections. The body never executes.
465
+
466
+ ```rill
467
+ [] -> fold(0) { $@ + $ }
468
+ # Result: 0
469
+
470
+ [] -> fold(42) { $@ + $ }
471
+ # Result: 42
472
+
473
+ [] -> fold |x, acc = 100| ($acc + $x)
474
+ # Result: 100
475
+ ```
476
+
477
+ ---
478
+
479
+ ## Comparison: each vs fold
480
+
481
+ Both `each` and `fold` support accumulators. The difference is in what they return.
482
+
483
+ | Feature | each | fold |
484
+ |---------|------|------|
485
+ | Returns | List of ALL results | Final result ONLY |
486
+ | Use case | Scan/prefix-sum | Reduce/aggregate |
487
+
488
+ ### Side-by-Side Example
489
+
490
+ ```rill
491
+ # each: returns every intermediate result
492
+ [1, 2, 3] -> each(0) { $@ + $ }
493
+ # Result: [1, 3, 6] (running totals)
494
+
495
+ # fold: returns only the final result
496
+ [1, 2, 3] -> fold(0) { $@ + $ }
497
+ # Result: 6 (final sum)
498
+ ```
499
+
500
+ ### When to Choose
501
+
502
+ Use `each` with accumulator when you need intermediate states (scan pattern):
503
+
504
+ ```rill
505
+ # Running balance
506
+ [100, -50, 200, -75] -> each(0) { $@ + $ }
507
+ # Result: [100, 50, 250, 175]
508
+ ```
509
+
510
+ Use `fold` when you only need the final result:
511
+
512
+ ```rill
513
+ # Final balance
514
+ [100, -50, 200, -75] -> fold(0) { $@ + $ }
515
+ # Result: 175
516
+ ```
517
+
518
+ ---
519
+
520
+ ## Chaining Operators
521
+
522
+ Combine operators for multi-stage transformations.
523
+
524
+ ```rill
525
+ # Double each element, then sum
526
+ [1, 2, 3] -> map { $ * 2 } -> fold(0) { $@ + $ }
527
+ # Result: 12
528
+
529
+ # Filter even numbers (using parallel filter)
530
+ [1, 2, 3, 4, 5] -> filter { ($ % 2) == 0 }
531
+ # Result: [2, 4]
532
+
533
+ # Complex pipeline: filter, then transform
534
+ [1, 2, 3, 4, 5] -> filter { $ > 2 } -> map { $ * 10 }
535
+ # Result: [30, 40, 50]
536
+ ```
537
+
538
+ ---
539
+
540
+ ## Closure Arity Rules
541
+
542
+ For inline closures with accumulators, specific rules apply.
543
+
544
+ ### Requirements
545
+
546
+ 1. At least 2 parameters — first receives element, last is accumulator
547
+ 2. Last parameter must have default — the default is the initial value
548
+ 3. Parameters between first and last must have defaults — no gaps
549
+ 4. Incoming args must exactly fill params before accumulator
550
+
551
+ ### Valid Closures
552
+
553
+ | Closure | Element Params | Accumulator | Notes |
554
+ |---------|---------------|-------------|-------|
555
+ | `\|x, acc = 0\|` | 1 required | `acc` | Standard case |
556
+ | `\|x = 1, acc = 0\|` | 1 optional | `acc` | Element overrides default |
557
+ | `\|a, b = 0, acc = 0\|` | 1 required, 1 optional | `acc` | `b` unused |
558
+
559
+ ### Invalid Closures
560
+
561
+ | Closure | Problem |
562
+ |---------|---------|
563
+ | `\|x\|` | No accumulator parameter |
564
+ | `\|acc = 0\|` | Only 1 param; element overwrites accumulator |
565
+ | `\|x, acc\|` | Accumulator has no default |
566
+ | `\|a, b, acc = 0\|` | Gap: `b` has no default |
567
+
568
+ ---
569
+
570
+ ## Error Cases
571
+
572
+ | Case | Example | Error |
573
+ |------|---------|-------|
574
+ | fold without accumulator | `[1,2] -> fold { $ }` | fold requires accumulator |
575
+ | fold closure missing default | `[1,2] -> fold \|x, acc\| body` | accumulator requires default |
576
+ | break in map | `[1,2] -> map { break }` | break not supported in map |
577
+ | break in fold | `[1,2] -> fold(0) { break }` | break not supported in fold |
578
+
579
+ ---
580
+
581
+ ## Iterating Different Types
582
+
583
+ ### Lists
584
+
585
+ ```rill
586
+ [1, 2, 3] -> each { $ * 2 }
587
+ # Result: [2, 4, 6]
588
+ ```
589
+
590
+ ### Strings
591
+
592
+ Iterates over characters.
593
+
594
+ ```rill
595
+ "abc" -> each { "{$}!" }
596
+ # Result: ["a!", "b!", "c!"]
597
+ ```
598
+
599
+ ### Dicts
600
+
601
+ Iterates over entries with `key` and `value` fields.
602
+
603
+ ```rill
604
+ [a: 1, b: 2] -> each { "{$.key}={$.value}" }
605
+ # Result: ["a=1", "b=2"]
606
+ ```
607
+
608
+ ---
609
+
610
+ ## Nested Collections
611
+
612
+ Process nested structures with nested operators.
613
+
614
+ ```rill
615
+ # Double nested values
616
+ [[1, 2], [3, 4]] -> map |inner| { $inner -> map { $ * 2 } }
617
+ # Result: [[2, 4], [6, 8]]
618
+
619
+ # Sum all nested values
620
+ [[1, 2], [3, 4]] -> fold(0) |inner, total = 0| { $total + ($inner -> fold(0) { $@ + $ }) }
621
+ # Result: 10
622
+ ```
623
+
624
+ ---
625
+
626
+ ## Performance Considerations
627
+
628
+ ### Sequential vs Parallel
629
+
630
+ | Scenario | Recommendation |
631
+ |----------|----------------|
632
+ | CPU-bound computation | `each` or `map` (similar performance) |
633
+ | I/O-bound operations | `map` (concurrent benefits) |
634
+ | Order-dependent logic | `each` (guaranteed order) |
635
+ | Stateful accumulation | `each` or `fold` (no parallel option) |
636
+
637
+ ### Memory
638
+
639
+ - `each` and `map` allocate result lists proportional to input size
640
+ - `fold` maintains constant memory (accumulator only)
641
+
642
+ ---
643
+
644
+ ## Quick Reference
645
+
646
+ ```rill
647
+ # each - sequential, all results
648
+ [1, 2, 3] -> each { $ * 2 } # [2, 4, 6]
649
+ [1, 2, 3] -> each(0) { $@ + $ } # [1, 3, 6] (running sum)
650
+
651
+ # map - parallel, all results
652
+ [1, 2, 3] -> map { $ * 2 } # [2, 4, 6]
653
+ ["a", "b"] -> map |x| { "{$x}!" } # ["a!", "b!"]
654
+
655
+ # filter - parallel, matching elements
656
+ [1, 2, 3, 4, 5] -> filter { $ > 2 } # [3, 4, 5]
657
+ |x| { $x % 2 == 0 } :> $isEven
658
+ [1, 2, 3, 4, 5] -> filter $isEven # [2, 4]
659
+
660
+ # fold - sequential, final result only
661
+ [1, 2, 3] -> fold(0) { $@ + $ } # 6
662
+ [1, 2, 3] -> fold |x, s = 0| ($s + $x) # 6
663
+
664
+ # Dict iteration
665
+ [a: 1, b: 2] -> each { $.key } # ["a", "b"]
666
+ [a: 1, b: 2] -> each { $.value } # [1, 2]
667
+
668
+ # Break (each only)
669
+ [1, 2, 3] -> each { ($ > 2) ? break ! $ } # [1, 2] (partial results)
670
+
671
+ # Empty collections
672
+ [] -> each { $ } # []
673
+ [] -> map { $ } # []
674
+ [] -> filter { $ } # []
675
+ [] -> fold(42) { $ } # 42
676
+ ```
677
+
678
+ ---
679
+
680
+ ## See Also
681
+
682
+ - [Iterators](08_iterators.md) — Lazy sequences with `range`, `repeat`, `.first()`
683
+ - [Reference](11_reference.md) — Complete language specification
684
+ - [Closures](06_closures.md) — Closure semantics and patterns
685
+ - [Guide](01_guide.md) — Beginner introduction
686
+ - [Examples](12_examples.md) — Workflow examples