plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
094fd48
— Peter John
2026-10-26T15:41:36+05:30
docs(plans): T9 fun* iterators with *T and yield; range moves to std
docs/plans/2026-10-26-zig-generics-and-numbers.md
CHANGED
|
@@ -208,3 +208,23 @@ Tests:
|
|
|
208
208
|
- `not_a_form_error`.
|
|
209
209
|
|
|
210
210
|
Bench: a loop over 10k units doing filter, then map, then fold. Compare the closure-method chain against the fused `for` form, and record the wasm size difference.
|
|
211
|
+
|
|
212
|
+
## Task T9: `fun*` iterators with `*T` and `yield` (user decisions; runs after the T8 review)
|
|
213
|
+
|
|
214
|
+
- **Declaration** (the user chose `fun*`): `fun* name[..](params) *T = …` or `fun* name[..](params) *(A, B) -> R = …`. `*T`/`*(A, B)` is what each step yields to the `for` binders, and the arity must equal the binder count. `-> R` is the optional result of the whole `for` (Unit if absent).
|
|
215
|
+
- `*T` is legal only on a `fun*`, and a `fun*` must have one: `fun* 'f' must declare its yield type (*T)` / `*T is only allowed on fun*`.
|
|
216
|
+
- `fun*` replaces `inline fun` plus the `block(...)` param: the `inline` keyword and the `block` param type are removed from the language, with migration hints in `legacySyntaxHint`.
|
|
217
|
+
- **`yield a, b`** is a statement, or an expression whose value is the user body's last expression. The checker infers the body's required type from how the `fun*` uses the yield value (`if yield x` gives Bool, `acc = yield acc, x` gives A, and an unused value gives anything). Expansion semantics are T8's: hygienic, one loop, no closure, no recursion, no `return` inside a `fun*`, and break/continue target the innermost loop around the `yield`.
|
|
218
|
+
- A `fun*` can only be used as a `for` source (`fun* 'f' can only be used as a for source`).
|
|
219
|
+
- **`range` moves to std** as `fun* range(start: Int, end: Int) *Int`, and the `for i := range n` sugar is removed (the user decided). Ruling: there is a single two-arg form, `range(0, n)`, because Plum has no overloading and keyword args are still matched by position. All ~67 uses in std, examples and tests migrate. The compiler's special range loop is deleted, so the only loop primitives left are `while` and `for` over a `fun*` or an iterable.
|
|
220
|
+
- **plum-std/Iter.plum** is rewritten with `fun*` and `yield`: `range`, `filter` (`*T -> List[T]`), `map` (`*T -> List[U]`), `find` (`*T -> T?`), `fold` (`*(A, T) -> A`), `any`, `all`, `count`, `indexed` (`*(Int, T)`), `zip` (`*(A, B)`), `each`.
|
|
221
|
+
|
|
222
|
+
Tests:
|
|
223
|
+
- `fun_star_range`, `yield_value_drives_filter` and `fold_yield_two`;
|
|
224
|
+
- `star_type_only_on_fun_star`, `fun_star_requires_star_type` and `fun_star_only_as_for_source`;
|
|
225
|
+
- `inline_keyword_removed_hint` and `range_sugar_removed_hint` (`for i := range n` gets the hint "write range(0, n)");
|
|
226
|
+
- `no_closure_in_expansion` (wasm inspection);
|
|
227
|
+
- `nested_fun_star_forms`;
|
|
228
|
+
- `binder_arity_mismatch`.
|
|
229
|
+
|
|
230
|
+
Update the README iteration section and the formatter/highlight queries.
|