added `iter.flatten`
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 7 Jun 2023 15:38:23 +0000 (10:38 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 7 Jun 2023 15:38:23 +0000 (10:38 -0500)
CHANGELOG
core/container/iter.onyx

index 8643caf1392345c9ba1590ad9b6cd2caceba0277..7fe412d072a8f56fbc27f4f5f910c0edca9e6d20 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -7,6 +7,7 @@ Additions:
     - `[captures] { body }` for blocks.
     - `[captures] ( expr )` for expressions.
 - `Optional.with` for running a block of code with the value in an Optional, if one is present.
+- `iter.flatten`
 
 Removals:
 - Remove old syntax for quoted blocks, `#quote` and `#()`.
index d7a78478f48a8a39332a0c2725056f6db02449cc..b39b5e9a128c79385a808064a26573f41d5f8649 100644 (file)
@@ -25,6 +25,7 @@ use core.intrinsics.types {type_is_struct}
     skip :: skip;
     skip_while :: skip_while;
     
+    flatten :: flatten;
     enumerate :: enumerate;
 
     fold :: fold;
@@ -422,6 +423,35 @@ zip :: (left_iterator: Iterator($T), right_iterator: Iterator($R)) -> Iterator(P
 }
 
 
+#doc """
+    Filters and maps at the same time.
+
+    If the provided function returns a None variant of Optional,
+    then the entry is discarded.
+
+    If the provided function returns `Some(x)`, then `x` is yielded.
+"""
+flatten :: (i: Iterator($T), f: (T) -> ? $R) -> Iterator(R) {
+    return generator(
+        &.{ i = i, f = f },
+
+        fi => {
+            while true {
+                v, cont := next(fi.i);
+                if !cont do break;
+
+                v2 := fi.f(v);
+                if v2 {
+                    return v2->unwrap(), true;
+                }
+            }
+            return .{}, false;
+        },
+
+        fi => { close(fi.i); }
+    );
+}
+
 
 #doc """
     Combines iterators by first yielding all values from