From: Brendan Hansen Date: Mon, 3 Jan 2022 02:25:22 +0000 (-0600) Subject: added variants of map and filter with contexts X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=ad9eb659184b872fa6fe144fedda9a0d67f75f57;p=onyx.git added variants of map and filter with contexts --- diff --git a/core/container/iter.onyx b/core/container/iter.onyx index 7f493037..a6bc7ee3 100644 --- a/core/container/iter.onyx +++ b/core/container/iter.onyx @@ -13,7 +13,8 @@ close :: (it: Iterator($T)) { it.close(it.data); } -filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) { +filter :: #match {} +#match filter (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) { FilterIterator :: struct (T: type_expr) { iterator: Iterator(T); predicate: (T) -> bool; @@ -49,7 +50,46 @@ filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) { }; } -map :: (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) { +#match filter (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool) -> Iterator(T) { + FilterIterator :: struct (T: type_expr, Ctx: type_expr) { + iterator: Iterator(T); + predicate: (T, Ctx) -> bool; + ctx: Ctx; + } + + filter_iterator := new(FilterIterator(T, Ctx)); + filter_iterator.iterator = it; + filter_iterator.predicate = predicate; + filter_iterator.ctx = ctx; + + next :: (fi: ^FilterIterator($T, $_)) -> (T, bool) { + value, cont := fi.iterator.next(fi.iterator.data); + if cont { + while !fi.predicate(value, fi.ctx) { + value, cont = fi.iterator.next(fi.iterator.data); + if !cont do return value, false; + } + + return value, true; + } else { + return value, false; + } + } + + close :: (fi: ^FilterIterator($T, $_)) { + if fi.iterator.close != null_proc do fi.iterator.close(fi.iterator.data); + cfree(fi); + } + + return .{ + data = filter_iterator, + next = #solidify next { T=T, _=Ctx }, + close = #solidify close { T=T, _=Ctx }, + }; +} + +map :: #match {} +#match map (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) { MapIterator :: struct (T: type_expr, R: type_expr) { iterator: Iterator(T); transform: (T) -> R; @@ -78,6 +118,37 @@ map :: (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) { }; } +#match map (it: Iterator($T), ctx: $Ctx, transform: (T, Ctx) -> $R) -> Iterator(R) { + MapIterator :: struct (T: type_expr, R: type_expr, Ctx: type_expr) { + iterator: Iterator(T); + transform: (T, Ctx) -> R; + ctx: Ctx; + } + + map_iterator := new(MapIterator(T, R, Ctx)); + map_iterator.iterator = it; + map_iterator.transform = transform; + map_iterator.ctx = ctx; + + next :: (mi: ^MapIterator($T, $R, $Ctx)) -> (R, bool) { + value, cont := mi.iterator.next(mi.iterator.data); + if !cont do return __zero_value(R), false; + + return mi.transform(value, mi.ctx), true; + } + + close :: (mi: ^MapIterator($T, $R, $Ctx)) { + if mi.iterator.close != null_proc do mi.iterator.close(mi.iterator.data); + cfree(mi); + } + + return .{ + data = map_iterator, + next = #solidify next { T=T, R=R, Ctx=Ctx }, + close = #solidify close { T=T, R=R, Ctx=Ctx }, + }; +} + take_one :: (it: Iterator($T), no_close := false) -> (T, bool) { ret, cont := it.next(it.data); if !cont && !no_close do it.close(it.data); diff --git a/tests/lazy_iterators.onyx b/tests/lazy_iterators.onyx index 8000388f..a87ff4cc 100644 --- a/tests/lazy_iterators.onyx +++ b/tests/lazy_iterators.onyx @@ -37,11 +37,14 @@ main :: (args: [] cstr) { // Hopefully soon, the following will be possible. { + lower_bound := 10; + addition := 42; + quick_iterator := count_iterator(1.0f, 20.0f) |> iter.map((x) => x * 2) - |> iter.filter((x) => x > 10) - |> iter.map((x) => x + 42) + |> iter.filter(lower_bound, (x, l) => x > ~~l) + |> iter.map(addition, (x, addition) => x + ~~addition) |> iter.take(5); for v: quick_iterator {