@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.
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +69 -0
- package/dist/cli.js.map +1 -0
- package/dist/demo.d.ts +6 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +121 -0
- package/dist/demo.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/lexer/errors.d.ts +9 -0
- package/dist/lexer/errors.d.ts.map +1 -0
- package/dist/lexer/errors.js +12 -0
- package/dist/lexer/errors.js.map +1 -0
- package/dist/lexer/helpers.d.ts +14 -0
- package/dist/lexer/helpers.d.ts.map +1 -0
- package/dist/lexer/helpers.js +30 -0
- package/dist/lexer/helpers.js.map +1 -0
- package/dist/lexer/index.d.ts +8 -0
- package/dist/lexer/index.d.ts.map +1 -0
- package/dist/lexer/index.js +8 -0
- package/dist/lexer/index.js.map +1 -0
- package/dist/lexer/operators.d.ts +11 -0
- package/dist/lexer/operators.d.ts.map +1 -0
- package/dist/lexer/operators.js +58 -0
- package/dist/lexer/operators.js.map +1 -0
- package/dist/lexer/readers.d.ts +12 -0
- package/dist/lexer/readers.d.ts.map +1 -0
- package/dist/lexer/readers.js +144 -0
- package/dist/lexer/readers.js.map +1 -0
- package/dist/lexer/state.d.ts +18 -0
- package/dist/lexer/state.d.ts.map +1 -0
- package/dist/lexer/state.js +37 -0
- package/dist/lexer/state.js.map +1 -0
- package/dist/lexer/tokenizer.d.ts +9 -0
- package/dist/lexer/tokenizer.d.ts.map +1 -0
- package/dist/lexer/tokenizer.js +100 -0
- package/dist/lexer/tokenizer.js.map +1 -0
- package/dist/lexer.d.ts +19 -0
- package/dist/lexer.d.ts.map +1 -0
- package/dist/lexer.js +344 -0
- package/dist/lexer.js.map +1 -0
- package/dist/parser/arithmetic.d.ts +16 -0
- package/dist/parser/arithmetic.d.ts.map +1 -0
- package/dist/parser/arithmetic.js +128 -0
- package/dist/parser/arithmetic.js.map +1 -0
- package/dist/parser/boolean.d.ts +15 -0
- package/dist/parser/boolean.d.ts.map +1 -0
- package/dist/parser/boolean.js +20 -0
- package/dist/parser/boolean.js.map +1 -0
- package/dist/parser/control-flow.d.ts +56 -0
- package/dist/parser/control-flow.d.ts.map +1 -0
- package/dist/parser/control-flow.js +167 -0
- package/dist/parser/control-flow.js.map +1 -0
- package/dist/parser/expressions.d.ts +23 -0
- package/dist/parser/expressions.d.ts.map +1 -0
- package/dist/parser/expressions.js +950 -0
- package/dist/parser/expressions.js.map +1 -0
- package/dist/parser/extraction.d.ts +48 -0
- package/dist/parser/extraction.d.ts.map +1 -0
- package/dist/parser/extraction.js +279 -0
- package/dist/parser/extraction.js.map +1 -0
- package/dist/parser/functions.d.ts +20 -0
- package/dist/parser/functions.d.ts.map +1 -0
- package/dist/parser/functions.js +96 -0
- package/dist/parser/functions.js.map +1 -0
- package/dist/parser/helpers.d.ts +94 -0
- package/dist/parser/helpers.d.ts.map +1 -0
- package/dist/parser/helpers.js +225 -0
- package/dist/parser/helpers.js.map +1 -0
- package/dist/parser/index.d.ts +49 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +73 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/literals.d.ts +37 -0
- package/dist/parser/literals.d.ts.map +1 -0
- package/dist/parser/literals.js +373 -0
- package/dist/parser/literals.js.map +1 -0
- package/dist/parser/parser-collect.d.ts +16 -0
- package/dist/parser/parser-collect.d.ts.map +1 -0
- package/dist/parser/parser-collect.js +125 -0
- package/dist/parser/parser-collect.js.map +1 -0
- package/dist/parser/parser-control.d.ts +20 -0
- package/dist/parser/parser-control.d.ts.map +1 -0
- package/dist/parser/parser-control.js +120 -0
- package/dist/parser/parser-control.js.map +1 -0
- package/dist/parser/parser-expr.d.ts +37 -0
- package/dist/parser/parser-expr.d.ts.map +1 -0
- package/dist/parser/parser-expr.js +639 -0
- package/dist/parser/parser-expr.js.map +1 -0
- package/dist/parser/parser-extract.d.ts +17 -0
- package/dist/parser/parser-extract.d.ts.map +1 -0
- package/dist/parser/parser-extract.js +222 -0
- package/dist/parser/parser-extract.js.map +1 -0
- package/dist/parser/parser-functions.d.ts +21 -0
- package/dist/parser/parser-functions.d.ts.map +1 -0
- package/dist/parser/parser-functions.js +155 -0
- package/dist/parser/parser-functions.js.map +1 -0
- package/dist/parser/parser-literals.d.ts +22 -0
- package/dist/parser/parser-literals.d.ts.map +1 -0
- package/dist/parser/parser-literals.js +288 -0
- package/dist/parser/parser-literals.js.map +1 -0
- package/dist/parser/parser-script.d.ts +21 -0
- package/dist/parser/parser-script.d.ts.map +1 -0
- package/dist/parser/parser-script.js +174 -0
- package/dist/parser/parser-script.js.map +1 -0
- package/dist/parser/parser-variables.d.ts +20 -0
- package/dist/parser/parser-variables.d.ts.map +1 -0
- package/dist/parser/parser-variables.js +146 -0
- package/dist/parser/parser-variables.js.map +1 -0
- package/dist/parser/parser.d.ts +49 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +54 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/parser/script.d.ts +14 -0
- package/dist/parser/script.d.ts.map +1 -0
- package/dist/parser/script.js +196 -0
- package/dist/parser/script.js.map +1 -0
- package/dist/parser/state.d.ts +40 -0
- package/dist/parser/state.d.ts.map +1 -0
- package/dist/parser/state.js +129 -0
- package/dist/parser/state.js.map +1 -0
- package/dist/parser/variables.d.ts +10 -0
- package/dist/parser/variables.d.ts.map +1 -0
- package/dist/parser/variables.js +215 -0
- package/dist/parser/variables.js.map +1 -0
- package/dist/runtime/ast-equals.d.ts +13 -0
- package/dist/runtime/ast-equals.d.ts.map +1 -0
- package/dist/runtime/ast-equals.js +447 -0
- package/dist/runtime/ast-equals.js.map +1 -0
- package/dist/runtime/builtins.d.ts +13 -0
- package/dist/runtime/builtins.d.ts.map +1 -0
- package/dist/runtime/builtins.js +180 -0
- package/dist/runtime/builtins.js.map +1 -0
- package/dist/runtime/callable.d.ts +88 -0
- package/dist/runtime/callable.d.ts.map +1 -0
- package/dist/runtime/callable.js +98 -0
- package/dist/runtime/callable.js.map +1 -0
- package/dist/runtime/context.d.ts +13 -0
- package/dist/runtime/context.d.ts.map +1 -0
- package/dist/runtime/context.js +73 -0
- package/dist/runtime/context.js.map +1 -0
- package/dist/runtime/core/callable.d.ts +171 -0
- package/dist/runtime/core/callable.d.ts.map +1 -0
- package/dist/runtime/core/callable.js +246 -0
- package/dist/runtime/core/callable.js.map +1 -0
- package/dist/runtime/core/context.d.ts +29 -0
- package/dist/runtime/core/context.d.ts.map +1 -0
- package/dist/runtime/core/context.js +154 -0
- package/dist/runtime/core/context.js.map +1 -0
- package/dist/runtime/core/equals.d.ts +9 -0
- package/dist/runtime/core/equals.d.ts.map +1 -0
- package/dist/runtime/core/equals.js +381 -0
- package/dist/runtime/core/equals.js.map +1 -0
- package/dist/runtime/core/eval/base.d.ts +65 -0
- package/dist/runtime/core/eval/base.d.ts.map +1 -0
- package/dist/runtime/core/eval/base.js +112 -0
- package/dist/runtime/core/eval/base.js.map +1 -0
- package/dist/runtime/core/eval/evaluator.d.ts +47 -0
- package/dist/runtime/core/eval/evaluator.d.ts.map +1 -0
- package/dist/runtime/core/eval/evaluator.js +73 -0
- package/dist/runtime/core/eval/evaluator.js.map +1 -0
- package/dist/runtime/core/eval/index.d.ts +57 -0
- package/dist/runtime/core/eval/index.d.ts.map +1 -0
- package/dist/runtime/core/eval/index.js +95 -0
- package/dist/runtime/core/eval/index.js.map +1 -0
- package/dist/runtime/core/eval/mixins/annotations.d.ts +19 -0
- package/dist/runtime/core/eval/mixins/annotations.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/annotations.js +146 -0
- package/dist/runtime/core/eval/mixins/annotations.js.map +1 -0
- package/dist/runtime/core/eval/mixins/closures.d.ts +49 -0
- package/dist/runtime/core/eval/mixins/closures.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/closures.js +479 -0
- package/dist/runtime/core/eval/mixins/closures.js.map +1 -0
- package/dist/runtime/core/eval/mixins/collections.d.ts +24 -0
- package/dist/runtime/core/eval/mixins/collections.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/collections.js +466 -0
- package/dist/runtime/core/eval/mixins/collections.js.map +1 -0
- package/dist/runtime/core/eval/mixins/control-flow.d.ts +27 -0
- package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/control-flow.js +369 -0
- package/dist/runtime/core/eval/mixins/control-flow.js.map +1 -0
- package/dist/runtime/core/eval/mixins/core.d.ts +24 -0
- package/dist/runtime/core/eval/mixins/core.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/core.js +335 -0
- package/dist/runtime/core/eval/mixins/core.js.map +1 -0
- package/dist/runtime/core/eval/mixins/expressions.d.ts +19 -0
- package/dist/runtime/core/eval/mixins/expressions.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/expressions.js +202 -0
- package/dist/runtime/core/eval/mixins/expressions.js.map +1 -0
- package/dist/runtime/core/eval/mixins/extraction.d.ts +10 -0
- package/dist/runtime/core/eval/mixins/extraction.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/extraction.js +250 -0
- package/dist/runtime/core/eval/mixins/extraction.js.map +1 -0
- package/dist/runtime/core/eval/mixins/literals.d.ts +23 -0
- package/dist/runtime/core/eval/mixins/literals.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/literals.js +180 -0
- package/dist/runtime/core/eval/mixins/literals.js.map +1 -0
- package/dist/runtime/core/eval/mixins/types.d.ts +20 -0
- package/dist/runtime/core/eval/mixins/types.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/types.js +109 -0
- package/dist/runtime/core/eval/mixins/types.js.map +1 -0
- package/dist/runtime/core/eval/mixins/variables.d.ts +34 -0
- package/dist/runtime/core/eval/mixins/variables.d.ts.map +1 -0
- package/dist/runtime/core/eval/mixins/variables.js +247 -0
- package/dist/runtime/core/eval/mixins/variables.js.map +1 -0
- package/dist/runtime/core/eval/types.d.ts +41 -0
- package/dist/runtime/core/eval/types.d.ts.map +1 -0
- package/dist/runtime/core/eval/types.js +10 -0
- package/dist/runtime/core/eval/types.js.map +1 -0
- package/dist/runtime/core/evaluate.d.ts +42 -0
- package/dist/runtime/core/evaluate.d.ts.map +1 -0
- package/dist/runtime/core/evaluate.debug.js +1251 -0
- package/dist/runtime/core/evaluate.js +1913 -0
- package/dist/runtime/core/evaluate.js.map +1 -0
- package/dist/runtime/core/execute.d.ts +26 -0
- package/dist/runtime/core/execute.d.ts.map +1 -0
- package/dist/runtime/core/execute.js +177 -0
- package/dist/runtime/core/execute.js.map +1 -0
- package/dist/runtime/core/signals.d.ts +19 -0
- package/dist/runtime/core/signals.d.ts.map +1 -0
- package/dist/runtime/core/signals.js +26 -0
- package/dist/runtime/core/signals.js.map +1 -0
- package/dist/runtime/core/types.d.ts +177 -0
- package/dist/runtime/core/types.d.ts.map +1 -0
- package/dist/runtime/core/types.js +50 -0
- package/dist/runtime/core/types.js.map +1 -0
- package/dist/runtime/core/values.d.ts +66 -0
- package/dist/runtime/core/values.d.ts.map +1 -0
- package/dist/runtime/core/values.js +240 -0
- package/dist/runtime/core/values.js.map +1 -0
- package/dist/runtime/evaluate.d.ts +32 -0
- package/dist/runtime/evaluate.d.ts.map +1 -0
- package/dist/runtime/evaluate.js +1111 -0
- package/dist/runtime/evaluate.js.map +1 -0
- package/dist/runtime/execute.d.ts +26 -0
- package/dist/runtime/execute.d.ts.map +1 -0
- package/dist/runtime/execute.js +121 -0
- package/dist/runtime/execute.js.map +1 -0
- package/dist/runtime/ext/builtins.d.ts +16 -0
- package/dist/runtime/ext/builtins.d.ts.map +1 -0
- package/dist/runtime/ext/builtins.js +528 -0
- package/dist/runtime/ext/builtins.js.map +1 -0
- package/dist/runtime/ext/content-parser.d.ts +83 -0
- package/dist/runtime/ext/content-parser.d.ts.map +1 -0
- package/dist/runtime/ext/content-parser.js +536 -0
- package/dist/runtime/ext/content-parser.js.map +1 -0
- package/dist/runtime/index.d.ts +28 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +34 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/signals.d.ts +19 -0
- package/dist/runtime/signals.d.ts.map +1 -0
- package/dist/runtime/signals.js +26 -0
- package/dist/runtime/signals.js.map +1 -0
- package/dist/runtime/types.d.ts +169 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +50 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/values.d.ts +50 -0
- package/dist/runtime/values.d.ts.map +1 -0
- package/dist/runtime/values.js +209 -0
- package/dist/runtime/values.js.map +1 -0
- package/dist/runtime.d.ts +254 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +2014 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +752 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +189 -0
- package/dist/types.js.map +1 -0
- package/docs/00_INDEX.md +65 -0
- package/docs/01_guide.md +390 -0
- package/docs/02_types.md +399 -0
- package/docs/03_variables.md +314 -0
- package/docs/04_operators.md +551 -0
- package/docs/05_control-flow.md +350 -0
- package/docs/06_closures.md +353 -0
- package/docs/07_collections.md +686 -0
- package/docs/08_iterators.md +330 -0
- package/docs/09_strings.md +205 -0
- package/docs/10_parsing.md +366 -0
- package/docs/11_reference.md +350 -0
- package/docs/12_examples.md +771 -0
- package/docs/13_modules.md +519 -0
- package/docs/14_host-integration.md +826 -0
- package/docs/15_grammar.ebnf +693 -0
- package/docs/16_conventions.md +696 -0
- package/docs/99_llm-reference.txt +300 -0
- package/docs/assets/logo.png +0 -0
- package/package.json +70 -0
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
# rill Core Examples
|
|
2
|
+
|
|
3
|
+
Examples demonstrating core language features for workflow orchestration.
|
|
4
|
+
|
|
5
|
+
> **Note:** These examples assume the host provides `prompt()`, `error()`, and other domain functions. rill is a vanilla language—all integrations come from the host runtime. Frontmatter is opaque to rill; the host parses it and provides named variables to the script context.
|
|
6
|
+
|
|
7
|
+
## Feature Implementation Workflow
|
|
8
|
+
|
|
9
|
+
Validates requirements, creates spec, iterates on review, then implements.
|
|
10
|
+
|
|
11
|
+
```rill
|
|
12
|
+
---
|
|
13
|
+
timeout: 00:10:00
|
|
14
|
+
args: requirements: string
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Phase 1: Validate requirements
|
|
18
|
+
prompt(<<EOF
|
|
19
|
+
Review the requirements document at {$requirements}.
|
|
20
|
+
Check for completeness and clarity.
|
|
21
|
+
Output READY if complete, or list missing elements.
|
|
22
|
+
EOF
|
|
23
|
+
) :> $validation
|
|
24
|
+
|
|
25
|
+
$validation -> ?(!.contains("READY")) {
|
|
26
|
+
error("Requirements incomplete: {$validation}")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Phase 2: Create specification
|
|
30
|
+
prompt(<<EOF
|
|
31
|
+
Create a technical specification from {$requirements}.
|
|
32
|
+
Include API design, data models, and component structure.
|
|
33
|
+
EOF
|
|
34
|
+
) :> $spec
|
|
35
|
+
|
|
36
|
+
"Specification created" -> log
|
|
37
|
+
|
|
38
|
+
# Phase 3: Review loop - iterate until approved
|
|
39
|
+
($spec -> .contains("REVISION")) @ {
|
|
40
|
+
prompt(<<EOF
|
|
41
|
+
Review this specification for issues:
|
|
42
|
+
{$}
|
|
43
|
+
|
|
44
|
+
Output APPROVED if ready, or REVISION REQUIRED with feedback.
|
|
45
|
+
EOF
|
|
46
|
+
) :> $review
|
|
47
|
+
|
|
48
|
+
$review -> ?(.contains("APPROVED")) { break }
|
|
49
|
+
|
|
50
|
+
# Apply feedback and continue
|
|
51
|
+
prompt(<<EOF
|
|
52
|
+
Update the specification based on this feedback:
|
|
53
|
+
{$review}
|
|
54
|
+
|
|
55
|
+
Original spec:
|
|
56
|
+
{$}
|
|
57
|
+
EOF
|
|
58
|
+
)
|
|
59
|
+
} :> $approved_spec
|
|
60
|
+
|
|
61
|
+
# Phase 4: Implementation
|
|
62
|
+
prompt(<<EOF
|
|
63
|
+
Implement the approved specification:
|
|
64
|
+
{$approved_spec}
|
|
65
|
+
|
|
66
|
+
Create the necessary files and tests.
|
|
67
|
+
EOF
|
|
68
|
+
) :> $implementation
|
|
69
|
+
|
|
70
|
+
# Phase 5: Verify
|
|
71
|
+
prompt("Run tests and verify implementation") :> $verification
|
|
72
|
+
|
|
73
|
+
$verification -> ?(.contains("PASS")) {
|
|
74
|
+
[0, "Workflow complete"]
|
|
75
|
+
} ! {
|
|
76
|
+
[1, "Verification failed: {$verification}"]
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Document-Driven Task Loop
|
|
81
|
+
|
|
82
|
+
Works through a checklist until complete.
|
|
83
|
+
|
|
84
|
+
```rill
|
|
85
|
+
---
|
|
86
|
+
args: plan: string
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
# Initial check
|
|
90
|
+
prompt("Read {$plan} and find the first unchecked item (- [ ])") :> $status
|
|
91
|
+
|
|
92
|
+
# Work loop
|
|
93
|
+
$status -> @(!.contains("ALL COMPLETE")) {
|
|
94
|
+
prompt(<<EOF
|
|
95
|
+
Based on this status:
|
|
96
|
+
{$}
|
|
97
|
+
|
|
98
|
+
1. Implement the identified unchecked item
|
|
99
|
+
2. Mark it complete in {$plan}
|
|
100
|
+
3. Check if any unchecked items remain
|
|
101
|
+
4. Output ALL COMPLETE if done, or describe next item
|
|
102
|
+
EOF
|
|
103
|
+
)
|
|
104
|
+
} :> $final
|
|
105
|
+
|
|
106
|
+
"Plan complete: {$final}" -> log
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Test-Fix Loop
|
|
110
|
+
|
|
111
|
+
Runs tests, fixes failures, repeats until passing.
|
|
112
|
+
|
|
113
|
+
```rill
|
|
114
|
+
---
|
|
115
|
+
args: target: string
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
# Run tests
|
|
119
|
+
prompt("Run tests for {$target} and report results") :> $result
|
|
120
|
+
|
|
121
|
+
# Fix loop
|
|
122
|
+
$result -> @(.contains("FAIL")) {
|
|
123
|
+
"Fixing failures..." -> log
|
|
124
|
+
|
|
125
|
+
prompt(<<EOF
|
|
126
|
+
Fix these test failures:
|
|
127
|
+
{$}
|
|
128
|
+
|
|
129
|
+
Make minimal changes. Then run tests again and report results.
|
|
130
|
+
EOF
|
|
131
|
+
)
|
|
132
|
+
} :> $final
|
|
133
|
+
|
|
134
|
+
$final -> ?(.contains("PASS")) {
|
|
135
|
+
"All tests passing"
|
|
136
|
+
} ! {
|
|
137
|
+
error("Could not fix all tests")
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Code Review
|
|
142
|
+
|
|
143
|
+
Reviews code against multiple criteria.
|
|
144
|
+
|
|
145
|
+
```rill
|
|
146
|
+
---
|
|
147
|
+
args: file: string
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
# Get file summary
|
|
151
|
+
prompt("Read and summarize {$file}") :> $summary
|
|
152
|
+
|
|
153
|
+
# Security check
|
|
154
|
+
prompt(<<EOF
|
|
155
|
+
Evaluate for SECURITY issues:
|
|
156
|
+
{$summary}
|
|
157
|
+
|
|
158
|
+
Output PASS, WARN, or FAIL with explanation.
|
|
159
|
+
EOF
|
|
160
|
+
) :> $security
|
|
161
|
+
|
|
162
|
+
# Performance check
|
|
163
|
+
prompt(<<EOF
|
|
164
|
+
Evaluate for PERFORMANCE issues:
|
|
165
|
+
{$summary}
|
|
166
|
+
|
|
167
|
+
Output PASS, WARN, or FAIL with explanation.
|
|
168
|
+
EOF
|
|
169
|
+
) :> $performance
|
|
170
|
+
|
|
171
|
+
# Check results
|
|
172
|
+
$security -> ?(.contains("FAIL")) {
|
|
173
|
+
error("Security review failed: {$security}")
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
$performance -> ?(.contains("FAIL")) {
|
|
177
|
+
error("Performance review failed: {$performance}")
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
"Code review passed"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Environment-Aware Deployment
|
|
184
|
+
|
|
185
|
+
Deploys based on environment configuration.
|
|
186
|
+
|
|
187
|
+
```rill
|
|
188
|
+
---
|
|
189
|
+
args: service: string
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
# Validate environment
|
|
193
|
+
$ENV.DEPLOY_ENV -> ?(.empty()) {
|
|
194
|
+
error("DEPLOY_ENV not set")
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# Environment-specific deployment
|
|
198
|
+
($ENV.DEPLOY_ENV == "production") ? {
|
|
199
|
+
prompt(<<EOF
|
|
200
|
+
Deploy {$service} to production.
|
|
201
|
+
- Run full test suite first
|
|
202
|
+
- Enable monitoring
|
|
203
|
+
- Use blue-green deployment
|
|
204
|
+
EOF
|
|
205
|
+
)
|
|
206
|
+
} ! ($ENV.DEPLOY_ENV == "staging") ? {
|
|
207
|
+
prompt(<<EOF
|
|
208
|
+
Deploy {$service} to staging.
|
|
209
|
+
- Run smoke tests
|
|
210
|
+
- Enable debug logging
|
|
211
|
+
EOF
|
|
212
|
+
)
|
|
213
|
+
} ! {
|
|
214
|
+
prompt("Deploy {$service} to development environment")
|
|
215
|
+
} :> $result
|
|
216
|
+
|
|
217
|
+
"Deployment complete" -> log
|
|
218
|
+
[0, "Deployed {$service} to {$ENV.DEPLOY_ENV}"]
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Retry Pattern
|
|
222
|
+
|
|
223
|
+
Retries an operation until success or max attempts. Use do-while since you always want at least one attempt:
|
|
224
|
+
|
|
225
|
+
```rill
|
|
226
|
+
---
|
|
227
|
+
args: operation: string
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
# Do-while: body runs first, then condition checked
|
|
231
|
+
^(limit: 5) @ {
|
|
232
|
+
prompt(<<EOF
|
|
233
|
+
Perform: {$operation}
|
|
234
|
+
|
|
235
|
+
Output SUCCESS, RETRY, or FAILED.
|
|
236
|
+
EOF
|
|
237
|
+
)
|
|
238
|
+
} ? (.contains("RETRY"))
|
|
239
|
+
|
|
240
|
+
# Loop exits when result doesn't contain RETRY
|
|
241
|
+
.contains("SUCCESS") ? [0, "Succeeded"] ! [1, "Failed: {$}"]
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
The do-while form eliminates the separate first-attempt code since the body always executes at least once.
|
|
245
|
+
|
|
246
|
+
## Inline Capture Pattern
|
|
247
|
+
|
|
248
|
+
Captures mid-chain for debugging or later reference while data continues flowing.
|
|
249
|
+
|
|
250
|
+
```rill
|
|
251
|
+
---
|
|
252
|
+
args: file: string
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
# Inline capture: value flows through $raw to log to conditional
|
|
256
|
+
prompt("Read {$file}") :> $raw -> log -> ?(.contains("ERROR")) {
|
|
257
|
+
error("Failed to read: {$raw}")
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
# Continue with $raw available for later use
|
|
261
|
+
prompt("Analyze this content:\n{$raw}") :> $analysis -> log -> ?(.empty()) {
|
|
262
|
+
error("Analysis produced no output")
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
# Both $raw and $analysis available
|
|
266
|
+
prompt(<<EOF
|
|
267
|
+
Compare the original:
|
|
268
|
+
{$raw}
|
|
269
|
+
|
|
270
|
+
With the analysis:
|
|
271
|
+
{$analysis}
|
|
272
|
+
EOF
|
|
273
|
+
)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Semantically, `:> $var ->` is `:> $var.set($) ->` — the capture acts like `log`, storing the value while passing it through unchanged.
|
|
277
|
+
|
|
278
|
+
## Type-Safe Variables
|
|
279
|
+
|
|
280
|
+
Uses type annotations to prevent accidental type changes during script execution.
|
|
281
|
+
|
|
282
|
+
```rill
|
|
283
|
+
---
|
|
284
|
+
args: file: string
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
# Define a typed helper closure
|
|
288
|
+
|input: string| {
|
|
289
|
+
prompt("Validate: {$input}") -> ?(.contains("VALID")) { true } ! { false }
|
|
290
|
+
} :> $validate:closure
|
|
291
|
+
|
|
292
|
+
# Capture with explicit type locks the variable
|
|
293
|
+
"processing" :> $status:string
|
|
294
|
+
"checking {$file}" :> $status # OK: same type
|
|
295
|
+
# 42 :> $status # ERROR: cannot assign number to string
|
|
296
|
+
|
|
297
|
+
# Closures are type-locked too
|
|
298
|
+
# "oops" :> $validate # ERROR: cannot assign string to closure
|
|
299
|
+
|
|
300
|
+
# Inline type annotation in pipe chain
|
|
301
|
+
prompt("Check {$file}") :> $result:string -> log -> ?(.contains("ERROR")) {
|
|
302
|
+
error($result)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
# Type annotations catch mistakes early
|
|
306
|
+
prompt("Analyze {$file}") :> $analysis:string
|
|
307
|
+
|
|
308
|
+
?(.contains("FAIL")) {
|
|
309
|
+
error("Analysis failed: {$analysis}")
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
[0, "Processing complete"]
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Pattern Extraction
|
|
316
|
+
|
|
317
|
+
Extracts specific information from responses.
|
|
318
|
+
|
|
319
|
+
```rill
|
|
320
|
+
---
|
|
321
|
+
args: logfile: string
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
prompt("Read {$logfile} and find all ERROR lines") :> $errors
|
|
325
|
+
|
|
326
|
+
$errors -> ?(.empty()) {
|
|
327
|
+
"No errors found"
|
|
328
|
+
} ! {
|
|
329
|
+
prompt(<<EOF
|
|
330
|
+
Analyze these errors and categorize them:
|
|
331
|
+
{$errors}
|
|
332
|
+
|
|
333
|
+
For each unique error type, suggest a fix.
|
|
334
|
+
EOF
|
|
335
|
+
) :> $analysis
|
|
336
|
+
|
|
337
|
+
"Error analysis complete" -> log
|
|
338
|
+
$analysis
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Multi-Phase Pipeline with Bailout
|
|
343
|
+
|
|
344
|
+
Each phase can halt the pipeline on failure.
|
|
345
|
+
|
|
346
|
+
```rill
|
|
347
|
+
---
|
|
348
|
+
args: file: string
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
# Multi-phase pipeline with early exit on errors
|
|
352
|
+
"content of {$file}" :> $content
|
|
353
|
+
|
|
354
|
+
$content -> .contains("ERROR") ? {
|
|
355
|
+
"Read failed" -> return
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
"analyzed: {$content}" :> $analysis
|
|
359
|
+
|
|
360
|
+
$analysis -> .contains("FAIL") ? {
|
|
361
|
+
"Analysis failed" -> return
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
"Pipeline complete: {$analysis}"
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Arithmetic in Loops
|
|
368
|
+
|
|
369
|
+
Uses bar-delimited arithmetic for calculations within workflow logic.
|
|
370
|
+
|
|
371
|
+
```rill
|
|
372
|
+
---
|
|
373
|
+
args: items: string
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
# Count items and calculate batch sizes
|
|
377
|
+
prompt("Count items in {$items}") -> .match("(\\d+) items") :> $m
|
|
378
|
+
|
|
379
|
+
$m -> ?(.empty()) {
|
|
380
|
+
error("Could not parse item count")
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
$m.groups[0] -> .num :> $count
|
|
384
|
+
|
|
385
|
+
# Calculate batches: ceil(count / 10)
|
|
386
|
+
(($count + 9) / 10) :> $batches
|
|
387
|
+
|
|
388
|
+
"Processing {$count} items in {$batches} batches" -> log
|
|
389
|
+
|
|
390
|
+
# Process each batch using range
|
|
391
|
+
range(1, $batches + 1) -> each {
|
|
392
|
+
$ :> $batch_num
|
|
393
|
+
(($batch_num - 1) * 10) :> $start
|
|
394
|
+
($start + 10) :> $end
|
|
395
|
+
|
|
396
|
+
prompt(<<EOF
|
|
397
|
+
Process batch {$batch_num} of {$batches}
|
|
398
|
+
Items {$start} through {$end}
|
|
399
|
+
EOF
|
|
400
|
+
)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
[0, "Processed all batches"]
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Signal-Based Workflow
|
|
407
|
+
|
|
408
|
+
Uses explicit signals for workflow control.
|
|
409
|
+
|
|
410
|
+
```rill
|
|
411
|
+
---
|
|
412
|
+
args: task: string
|
|
413
|
+
exceptions:
|
|
414
|
+
- ":::BLOCKED:::"
|
|
415
|
+
- ":::NEEDS_HUMAN:::"
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
prompt(<<EOF
|
|
419
|
+
Work on this task: {$task}
|
|
420
|
+
|
|
421
|
+
Rules:
|
|
422
|
+
- Output :::BLOCKED::: if you need information you don't have
|
|
423
|
+
- Output :::NEEDS_HUMAN::: if human judgment is required
|
|
424
|
+
- Output :::DONE::: when complete
|
|
425
|
+
EOF
|
|
426
|
+
) :> $result
|
|
427
|
+
|
|
428
|
+
$result -> @(!.contains(":::DONE:::")) {
|
|
429
|
+
prompt(<<EOF
|
|
430
|
+
Continue working on: {$task}
|
|
431
|
+
|
|
432
|
+
Previous progress:
|
|
433
|
+
{$}
|
|
434
|
+
|
|
435
|
+
Remember the signal rules.
|
|
436
|
+
EOF
|
|
437
|
+
)
|
|
438
|
+
} :> $final
|
|
439
|
+
|
|
440
|
+
"Task complete: {$final}" -> log
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Extraction Operators
|
|
444
|
+
|
|
445
|
+
Demonstrates destructuring, slicing, and enumeration.
|
|
446
|
+
|
|
447
|
+
### Destructuring Function Results
|
|
448
|
+
|
|
449
|
+
```rill
|
|
450
|
+
# Destructure list results into named variables
|
|
451
|
+
["test output", 0] -> *<$out, $code>
|
|
452
|
+
|
|
453
|
+
$code -> .gt(0) ? {
|
|
454
|
+
"Tests failed:\n{$out}" -> log
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
"All tests passed" -> log
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Processing Structured Data
|
|
461
|
+
|
|
462
|
+
```rill
|
|
463
|
+
# Process list of [file, mode] pairs
|
|
464
|
+
[
|
|
465
|
+
["src/auth.ts", "security"],
|
|
466
|
+
["src/api.ts", "performance"],
|
|
467
|
+
["src/db.ts", "security"]
|
|
468
|
+
] -> each {
|
|
469
|
+
$ -> *<$f, $mode>
|
|
470
|
+
"Review {$f} for {$mode} issues" -> log
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### Enumerated Progress
|
|
475
|
+
|
|
476
|
+
```rill
|
|
477
|
+
# ...
|
|
478
|
+
# enumerate($tasks) -> each {
|
|
479
|
+
# "[{$.index + 1}/{$tasks.len}] Processing: {$.value}" -> log()
|
|
480
|
+
# prompt("Complete task: {$.value}")
|
|
481
|
+
# }
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### Slicing Results
|
|
485
|
+
|
|
486
|
+
```rill
|
|
487
|
+
# Get first 3 items
|
|
488
|
+
["a", "b", "c", "d", "e"] -> /<:3>
|
|
489
|
+
# ["a", "b", "c"]
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
```rill
|
|
493
|
+
# Process in reverse order
|
|
494
|
+
["a", "b", "c"] -> /<::-1>
|
|
495
|
+
# ["c", "b", "a"]
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Dict Iteration
|
|
499
|
+
|
|
500
|
+
```rill
|
|
501
|
+
# Use .entries to iterate over dict key-value pairs
|
|
502
|
+
[host: "localhost", port: 8080] -> .entries -> each {
|
|
503
|
+
"{$[0]}={$[1]}"
|
|
504
|
+
} -> .join("\n")
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Args Type and Strict Invocation
|
|
508
|
+
|
|
509
|
+
Explicit argument unpacking with validation.
|
|
510
|
+
|
|
511
|
+
### Positional Args
|
|
512
|
+
|
|
513
|
+
```rill
|
|
514
|
+
# Define a function
|
|
515
|
+
|a, b, c| { "{$a}-{$b}-{$c}" } :> $fmt
|
|
516
|
+
|
|
517
|
+
# Create args from tuple and invoke
|
|
518
|
+
*[1, 2, 3] -> $fmt() # "1-2-3"
|
|
519
|
+
|
|
520
|
+
# Store args for later use
|
|
521
|
+
*[1, 2, 3] :> $myArgs
|
|
522
|
+
$myArgs -> $fmt() # "1-2-3"
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### Named Args
|
|
526
|
+
|
|
527
|
+
```rill
|
|
528
|
+
# Named args match by parameter name, order doesn't matter
|
|
529
|
+
|width, height|($width * $height) :> $area
|
|
530
|
+
|
|
531
|
+
*[height: 20, width: 10] -> $area() # 200
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Parameter Defaults
|
|
535
|
+
|
|
536
|
+
```rill
|
|
537
|
+
# Defaults provide opt-in leniency
|
|
538
|
+
|x, y = 10, z = 20|($x + $y + $z) :> $fn
|
|
539
|
+
|
|
540
|
+
*[5] -> $fn() # 35 (5 + 10 + 20)
|
|
541
|
+
*[x: 5, z: 30] -> $fn() # 45 (5 + 10 + 30)
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Type Checking with Global Functions
|
|
545
|
+
|
|
546
|
+
```rill
|
|
547
|
+
# Use type() to inspect values
|
|
548
|
+
42 -> type # "number"
|
|
549
|
+
"hello" -> type # "string"
|
|
550
|
+
[1, 2] -> type # "list"
|
|
551
|
+
*[1, 2] -> type # "tuple"
|
|
552
|
+
[a: 1] -> type # "dict"
|
|
553
|
+
|
|
554
|
+
# Use json() to serialize
|
|
555
|
+
[name: "test", count: 42] -> json
|
|
556
|
+
# '{"name":"test","count":42}'
|
|
557
|
+
|
|
558
|
+
# Use log() to debug while continuing pipe
|
|
559
|
+
"processing" -> log -> .len # logs "processing", returns 10
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## Parsing LLM Output
|
|
563
|
+
|
|
564
|
+
Built-in functions for extracting structured data from LLM responses.
|
|
565
|
+
|
|
566
|
+
### Auto-Detect with `parse_auto`
|
|
567
|
+
|
|
568
|
+
```rill
|
|
569
|
+
# parse_auto detects and extracts structured content
|
|
570
|
+
"{{\"status\": \"ok\", \"count\": 42}}" -> parse_auto :> $result
|
|
571
|
+
|
|
572
|
+
$result.type -> log # "json"
|
|
573
|
+
$result.data.status -> log # "ok"
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
For XML content, use `parse_xml` for more precise extraction:
|
|
577
|
+
|
|
578
|
+
```rill
|
|
579
|
+
"<response>200</response>" -> parse_xml("response")
|
|
580
|
+
# "200"
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Extract JSON from Fenced Blocks
|
|
584
|
+
|
|
585
|
+
```rill
|
|
586
|
+
# LLM returns: "Here's the config:\n```json\n{...}\n```"
|
|
587
|
+
prompt("Generate JSON config") -> parse_fence("json") -> parse_json :> $config
|
|
588
|
+
|
|
589
|
+
# Access parsed data
|
|
590
|
+
$config.host -> log
|
|
591
|
+
$config.port -> log
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Extract XML Tags (Claude-Style)
|
|
595
|
+
|
|
596
|
+
```rill
|
|
597
|
+
# LLM returns: "<thinking>...</thinking><answer>...</answer>"
|
|
598
|
+
prompt("Analyze step by step") :> $response
|
|
599
|
+
|
|
600
|
+
# Extract thinking for logging
|
|
601
|
+
$response -> parse_xml("thinking") -> log
|
|
602
|
+
|
|
603
|
+
# Extract and parse answer
|
|
604
|
+
$response -> parse_xml("answer") -> parse_json :> $answer
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### Parse Tool Calls
|
|
608
|
+
|
|
609
|
+
```rill
|
|
610
|
+
prompt(<<EOF
|
|
611
|
+
What function should I call?
|
|
612
|
+
Return in format: <tool><name>func</name><args>{...}</args></tool>
|
|
613
|
+
EOF
|
|
614
|
+
) :> $response
|
|
615
|
+
|
|
616
|
+
$response -> parse_xml("tool") :> $tool
|
|
617
|
+
$tool -> parse_xml("name") :> $fn_name
|
|
618
|
+
$tool -> parse_xml("args") -> parse_json :> $fn_args
|
|
619
|
+
|
|
620
|
+
# Call the function
|
|
621
|
+
call($fn_name, $fn_args)
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
### Process Checklists
|
|
625
|
+
|
|
626
|
+
```rill
|
|
627
|
+
# parse_checklist extracts checkbox items as [done, text] pairs
|
|
628
|
+
"- [ ] Deploy to staging\n- [x] Run tests\n- [ ] Update docs" -> parse_checklist :> $tasks
|
|
629
|
+
|
|
630
|
+
# Filter incomplete tasks
|
|
631
|
+
$tasks -> filter |task| { !$task.at(0) } -> each |task| {
|
|
632
|
+
"TODO: " -> log
|
|
633
|
+
$task.at(1) -> log
|
|
634
|
+
}
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Parse Frontmatter Documents
|
|
638
|
+
|
|
639
|
+
```rill
|
|
640
|
+
# parse_frontmatter extracts YAML header and body
|
|
641
|
+
"---\ntitle: Guide\nstatus: draft\n---\nContent here" -> parse_frontmatter :> $doc
|
|
642
|
+
|
|
643
|
+
$doc.meta.title -> log # "Guide"
|
|
644
|
+
$doc.body -> log # "Content here"
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### Multi-Block Extraction
|
|
648
|
+
|
|
649
|
+
```rill
|
|
650
|
+
# parse_fences extracts all fenced code blocks
|
|
651
|
+
"```python\nprint(1)\n```\n```js\nconsole.log(1)\n```" -> parse_fences -> each {
|
|
652
|
+
$.lang -> log
|
|
653
|
+
$.content -> log
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### Structured Response Validation
|
|
658
|
+
|
|
659
|
+
```rill
|
|
660
|
+
# Validate parsed content before use
|
|
661
|
+
"{{\"status\": \"ok\", \"items\": [1, 2, 3]}}" -> parse_auto :> $result
|
|
662
|
+
|
|
663
|
+
($result.type != "json") ? {
|
|
664
|
+
"Expected JSON" -> log
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
$result.data.status -> log # "ok"
|
|
668
|
+
$result.data.items -> each { $ -> log }
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
## Collection Operations
|
|
672
|
+
|
|
673
|
+
Pipeline operators for map, reduce, find, and aggregate patterns.
|
|
674
|
+
|
|
675
|
+
### Map with Parallel Spread
|
|
676
|
+
|
|
677
|
+
```rill
|
|
678
|
+
# Define closure first, then use it
|
|
679
|
+
|x| { $x * 2 } :> $double
|
|
680
|
+
[1, 2, 3, 4, 5] -> map $double
|
|
681
|
+
# [2, 4, 6, 8, 10]
|
|
682
|
+
|
|
683
|
+
# Map with inline block
|
|
684
|
+
["alice", "bob", "carol"] -> map { "Hello, {$}!" }
|
|
685
|
+
# ["Hello, alice!", "Hello, bob!", "Hello, carol!"]
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
### Filter with Parallel Filter
|
|
689
|
+
|
|
690
|
+
```rill
|
|
691
|
+
# Keep elements matching condition (block form)
|
|
692
|
+
[1, 2, 3, 4, 5] -> filter { .gt(2) }
|
|
693
|
+
# [3, 4, 5]
|
|
694
|
+
|
|
695
|
+
# Filter with closure predicate
|
|
696
|
+
|x| { $x % 2 == 0 } :> $even
|
|
697
|
+
[1, 2, 3, 4, 5, 6] -> filter $even
|
|
698
|
+
# [2, 4, 6]
|
|
699
|
+
|
|
700
|
+
# Filter non-empty strings
|
|
701
|
+
["hello", "", "world", ""] -> filter { !.empty }
|
|
702
|
+
# ["hello", "world"]
|
|
703
|
+
|
|
704
|
+
# Chain filter and map
|
|
705
|
+
|x| { $x * 2 } :> $dbl
|
|
706
|
+
[1, 2, 3, 4, 5] -> filter { .gt(2) } -> map $dbl
|
|
707
|
+
# [6, 8, 10]
|
|
708
|
+
|
|
709
|
+
# Filter structured data
|
|
710
|
+
[
|
|
711
|
+
[name: "alice", age: 30],
|
|
712
|
+
[name: "bob", age: 17],
|
|
713
|
+
[name: "carol", age: 25]
|
|
714
|
+
] -> filter { $.age -> .ge(18) }
|
|
715
|
+
# [[name: "alice", age: 30], [name: "carol", age: 25]]
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
### Reduce with Sequential Spread
|
|
719
|
+
|
|
720
|
+
```rill
|
|
721
|
+
# Chain transformations
|
|
722
|
+
|s|"{$s} -> validated" :> $validate
|
|
723
|
+
|s|"{$s} -> processed" :> $process
|
|
724
|
+
|s|"{$s} -> complete" :> $complete
|
|
725
|
+
|
|
726
|
+
"input" -> @[$validate, $process, $complete]
|
|
727
|
+
# "input -> validated -> processed -> complete"
|
|
728
|
+
|
|
729
|
+
# Numeric reduction
|
|
730
|
+
|x|($x + 10) :> $add10
|
|
731
|
+
|x|($x * 2) :> $double
|
|
732
|
+
|
|
733
|
+
5 -> @[$add10, $double, $add10]
|
|
734
|
+
# ((5 + 10) * 2) + 10 = 40
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
### Find First Match
|
|
738
|
+
|
|
739
|
+
```rill
|
|
740
|
+
# Find first element matching condition
|
|
741
|
+
[1, 2, 3, 4, 5] -> each {
|
|
742
|
+
.gt(3) ? { $ -> break }
|
|
743
|
+
} :> $found
|
|
744
|
+
# 4
|
|
745
|
+
|
|
746
|
+
# Find with default
|
|
747
|
+
[1, 2, 3] -> each {
|
|
748
|
+
.gt(10) ? { $ -> break }
|
|
749
|
+
} :> $result
|
|
750
|
+
$result -> .empty ? { "not found" } ! { "found: {$result}" }
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
### Aggregate/Sum
|
|
754
|
+
|
|
755
|
+
```rill
|
|
756
|
+
# Sum numbers using fold
|
|
757
|
+
[10, 20, 30, 40] -> fold(0) { $@ + $ }
|
|
758
|
+
# 100
|
|
759
|
+
|
|
760
|
+
# Count matching elements using filter
|
|
761
|
+
$items -> filter { .contains("error") } -> .len :> $count
|
|
762
|
+
"Found {$count} errors" -> log
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
### Transform and Collect
|
|
766
|
+
|
|
767
|
+
```rill
|
|
768
|
+
# Process items, collect results using map
|
|
769
|
+
["file1.txt", "file2.txt", "file3.txt"] -> map { "analyzed: {$}" } -> .join("\n")
|
|
770
|
+
# "analyzed: file1.txt\nanalyzed: file2.txt\nanalyzed: file3.txt"
|
|
771
|
+
```
|