diff --git a/changelog.md b/changelog.md index 8b53b9af0..cd81ab3f2 100644 --- a/changelog.md +++ b/changelog.md @@ -14,7 +14,8 @@ This version is not yet released. If you are reading this on the website, then t - [`insert`](https://uiua.org/docs/insert) - [`remove`](https://uiua.org/docs/remove) - Add experimental [`bind`](https://uiua.org/docs/bind) modifier, which binds local values within a function -- [`fill` `⬚`](https://uiua.org/docs/fill) can now be used to specify default accumulators for [`reduce` `/`](https://uiua.org/docs/reduce) +- [`fill` `⬚`](https://uiua.org/docs/fill) can now be used to specify default accumulators for [`reduce` `/`](https://uiua.org/docs/reduce), [`group` `⊕`](https://uiua.org/docs/group), and [`partition` `⊜`](https://uiua.org/docs/partition) + - Reducing [`group` `⊕`](https://uiua.org/docs/group) and [`partition` `⊜`](https://uiua.org/docs/partition) no longer take a required accumulator ### Interpreter - The internal byte array type is now used in more places, which should improve performance a bit - Lots of bug and crash fixes diff --git a/src/algorithm/loops.rs b/src/algorithm/loops.rs index 44bb4d1b5..d9a4b2590 100644 --- a/src/algorithm/loops.rs +++ b/src/algorithm/loops.rs @@ -340,10 +340,18 @@ fn collapse_groups( } } (2, 1) => { - let mut acc = env.pop(1)?; - let indices = env.pop(2)?.as_ints(env, red_indices_error)?; - let values = env.pop(3)?; - let groups = get_groups(values, &indices, env)?; + let indices = env.pop(1)?.as_ints(env, red_indices_error)?; + let values = env.pop(2)?; + let mut groups = get_groups(values, &indices, env)?.into_iter(); + let mut acc = match env.box_fill() { + Ok(acc) => acc.0, + Err(e) => groups.next().ok_or_else(|| { + env.error(format!( + "Cannot do aggregating {} with no groups{e}", + prim.format() + )) + })?, + }; for row in groups { env.push(row); env.push(acc); diff --git a/src/check.rs b/src/check.rs index 9fa3e62e5..fe94d61e2 100644 --- a/src/check.rs +++ b/src/check.rs @@ -336,19 +336,7 @@ impl<'a> VirtualEnv<'a> { } Group | Partition => { let sig = self.pop_func()?.signature(); - let args = match sig.args { - 0 => 2, - 1 => 2, - 2 => 3, - _ => { - return Err(format!( - "{prim}'s function must take at most 2 arguments, \ - but its signature is {sig}", - ) - .into()) - } - }; - self.handle_args_outputs(args, sig.outputs)?; + self.handle_args_outputs(2, sig.outputs)?; } Spawn => { let sig = self.pop_func()?.signature(); diff --git a/src/primitive/defs.rs b/src/primitive/defs.rs index 0a095532c..7f8560436 100644 --- a/src/primitive/defs.rs +++ b/src/primitive/defs.rs @@ -1168,8 +1168,8 @@ primitive!( /// The function then processes each group in order. The result depends on what the function is. /// If the function takes 0 or 1 arguments, then [group] behaves like [rows]. This is called *iterating* [group]. /// ex: ⊕∘ [0 2 2 1 0 1] [1 2 3 4 5 6] - /// If the function takes 2 or more arguments, then [group] requires an accumulator and behaves like [fold]. This is called *accumulating* [group]. - /// ex: ⊕⊂ [] [0 2 2 1 0 1] [1 2 3 4 5 6] + /// If the function takes 2 or more arguments, then [group] behaves like [reduce]. This is called *reducing* [group]. + /// ex: ⊕⊂ [0 2 2 1 0 1] [1 2 3 4 5 6] /// If the values returned by the function do not have the same [shape], concatenation will fail. /// ex! ⊕∘ [0 1 0 2 1 1] [1 2 3 4 5 6] /// It is common to use [box] to encapsulate groups of different [shape]s. @@ -1198,8 +1198,8 @@ primitive!( /// The function then processes each group in order. The result depends on what the function is. /// If the function takes 0 or 1 arguments, then [partition] behaves like [rows]. This is called *iterating* [partition]. /// ex: ⊜∘ [0 0 2 2 1 1 3 3] [1 2 3 4 5 6 7 8] - /// If the function takes 2 or more arguments, then [partition] requires an accumulator and behaves like [fold]. This is called *accumulating* [partition]. - /// ex: ⊜⊂ [] [0 0 2 2 1 1 3 3] [1 2 3 4 5 6 7 8] + /// If the function takes 2 or more arguments, then [partition] behaves like [reduce]. This is called *reducing* [partition]. + /// ex: ⊜⊂ [0 0 2 2 1 1 3 3] [1 2 3 4 5 6 7 8] /// If the values returned by the function do not have the same [shape], concatenation will fail. /// ex! ⊜∘ [0 2 3 3 3 0 1 1] [1 2 3 4 5 6 7 8] /// It is common to use [box] to encapsulate groups of different [shape]s. diff --git a/tests/loops.ua b/tests/loops.ua index 932154db0..202f95489 100644 --- a/tests/loops.ua +++ b/tests/loops.ua @@ -46,10 +46,10 @@ ⍤⊃⋅∘≍ ↯0_3[] ≡(⊂⊂) [] 5 [] ⍤⊃⋅∘≍ ↯0_3[] ≡(⊂⊂) 5 [] [] -⍤⊃⋅∘≍ ⇡6 ⊜⊂ [] [1 1 2 2 3 3] ⇡6 -⍤⊃⋅∘≍ ⇡6 /⊂⊜∘[1 1 2 2 3 3] ⇡6 -⍤⊃⋅∘≍ ⇡6 ⊕⊂ [] [0 0 1 1 2 2] ⇡6 -⍤⊃⋅∘≍ ⇡6 /⊂⊕∘[0 0 1 1 2 2] ⇡6 +⍤⊃⋅∘≍ ⇡6 ⊜⊂ [1 1 2 2 3 3] ⇡6 +⍤⊃⋅∘≍ ⇡6 /⊂⊜∘ [1 1 2 2 3 3] ⇡6 +⍤⊃⋅∘≍ ⇡6 ⊕⊂ [0 0 1 1 2 2] ⇡6 +⍤⊃⋅∘≍ ⇡6 /⊂⊕∘ [0 0 1 1 2 2] ⇡6 ⍤⊃⋅∘≍ 1024 ⍢(×2)(<1000) 1 ⍤⊃⋅∘≍ 1024 ⍢(×2)(<1000.) 1