Last active
June 5, 2025 16:52
-
-
Save osa1/7506e9a5074dc54f75c09e5767209f86 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class Sequence<Element> { | |
void forEach(void Function(Element) consumer); | |
} | |
class CountFrom implements Sequence<int> { | |
final int from; | |
CountFrom(this.from); | |
@override | |
void forEach(void Function(int) consumer) { | |
for (int i = from; ; i += 1) { | |
consumer(i); | |
} | |
} | |
} | |
class Empty implements Sequence<int> { | |
@override | |
void forEach(void Function(int) consumer) {} | |
} | |
class AppendAfter<Element> implements Sequence<Element> { | |
final Sequence<Element> first; | |
final Sequence<Element> second; | |
final int amount; | |
AppendAfter(this.first, this.amount, this.second); | |
@override | |
void forEach(void Function(Element) consumer) { | |
try { | |
int count = amount; | |
first.forEach((element) { | |
// Note: if you change the `count--` below to update `count` when not | |
// throwing an exception, this works as expected. | |
// | |
// The point is, outer `AppendAfter` handler throws an exception that | |
// is caught by the inner `AppendAfter`, which then leaves inner | |
// `AppendAfter` in an invalid state where `count` is negative. | |
if (count-- == 0) { | |
throw AppendAfterException(); | |
} | |
consumer(element); | |
}); | |
} on AppendAfterException {} | |
second.forEach(consumer); | |
} | |
} | |
class AppendAfterException {} | |
void main() { | |
// final simple = AppendAfter(CountFrom(0), 5, Empty()); | |
// simple.forEach((i) => print(i)); | |
final complex = AppendAfter(AppendAfter(CountFrom(0), 10, CountFrom(20)), 5, Empty()); | |
complex.forEach((i) => print(i)); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait Sequence[seq, t, exn]: | |
forEach(self: seq, consumer: Fn(t) / exn) / exn | |
# ------------------------------------------------------------------------------ | |
type CountFrom: | |
from: U32 | |
impl Sequence[CountFrom, U32, exn]: | |
forEach(self: CountFrom, consumer: Fn(U32) / exn) / exn: | |
let i = self.from | |
loop: | |
consumer(i) | |
i += 1 | |
# ------------------------------------------------------------------------------ | |
type AppendAfter[s1, s2]: | |
seq1: s1 | |
seq2: s2 | |
amt: U32 | |
impl[Sequence[s1, t, [AppendAfterStop, ..exn]], Sequence[s2, t, [AppendAfterStop, ..exn]]] | |
Sequence[AppendAfter[s1, s2], t, [AppendAfterStop, ..exn]]: | |
forEach( | |
self: AppendAfter[s1, s2], | |
consumer: Fn(t) / [AppendAfterStop, ..exn] | |
) / [AppendAfterStop, ..exn]: | |
match try({ | |
self.seq1.forEach(fn(i: t) / [AppendAfterStop, ..exn] { | |
# Weird way to update `self.amt`, but this is needed to demonstrate that issue with | |
# outer `AppendAfter`'s exception being caught by the inner `AppendAfter`. | |
let amt = self.amt | |
self.amt -= 1 | |
if amt == 0: | |
throw(~AppendAfterStop) | |
consumer(i) | |
}) | |
}): | |
Result.Ok(()) | Result.Err(~AppendAfterStop): | |
self.seq2.forEach(consumer) | |
# ------------------------------------------------------------------------------ | |
type EmptySeq: | |
EmptySeq | |
impl Sequence[EmptySeq, t, exn]: | |
forEach(self: EmptySeq, consumer: Fn(t) / exn) / exn: | |
() | |
# ------------------------------------------------------------------------------ | |
main(): | |
let seq = | |
AppendAfter( | |
seq1 = AppendAfter(seq1 = CountFrom(from = 0), seq2 = CountFrom(from = 20), amt = 10), | |
seq2 = EmptySeq.EmptySeq, | |
amt = 5, | |
) | |
try[[AppendAfterStop], (), []]({ | |
seq.forEach(fn(i: U32) { | |
print(i) | |
}) | |
}) | |
() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment