iterator work

improve performance of split, chars, chars_ref
properly implement lily.iter.Iterator.fold
partially implement lily.iter.Iterator.collect
fix lily.iter.Skip logic
code cleanup
write proposed iterator spec
This commit is contained in:
koniifer 2025-01-18 18:49:46 +00:00
parent bfe75481e3
commit 33cf8d7209
6 changed files with 71 additions and 57 deletions

View file

@ -1,2 +1,20 @@
# iterators
## spec to-be-defined
## spec to-be-defined
## proposed spec:
```rust
.{IterNext, Iterator} := @use("lily").iter
Iterable := struct {
// ! required
// IterNext == struct { finished: bool, val: T }
next := fn(self: ^Self): IterNext(T)
into_iter := fn(self: Self): Iterator(Self)
// ! proposed
// addition of these two would allow for cheap implementation of `skip`, and `nth` in lily.iter.Iterator
peek := fn(self: ^Self): IterNext(T)
advance := fn(self: ^Self, n: uint): IterNext(T)
// ! proposed (waiting on compiler)
iter := fn(self: ^Self): Iterator(^Self)
}

View file

@ -5,8 +5,12 @@ Item := fn($Key: type, $Value: type): type return packed struct {
value: Value,
}
Bucket := fn($Key: type, $Value: type, $Allocator: type): type return Vec(Item(Key, Value), Allocator)
Buckets := fn($Key: type, $Value: type, $Allocator: type): type return Vec(Bucket(Key, Value, Allocator), Allocator)
Bucket := fn($Key: type, $Value: type, $Allocator: type): type {
return Vec(Item(Key, Value), Allocator)
}
Buckets := fn($Key: type, $Value: type, $Allocator: type): type {
return Vec(Bucket(Key, Value, Allocator), Allocator)
}
HashMap := fn($Key: type, $Value: type, $Hasher: type, $Allocator: type): type return struct {
allocator: ^Allocator,

View file

@ -69,9 +69,6 @@ Vec := fn($T: type, $Allocator: type): type return struct {
i := 0
loop if self.get(i) == rhs return i else if i == self.slice.len return null else i += 1
}
$into_iter := fn(self: Self): iter.Iterator(iter.SliceIter(T)) {
return .(.(self.slice, 0))
}
$sort := fn(self: ^Self): void {
_ = quicksort(compare, self.slice, 0, self.slice.len - 1)
}

View file

@ -46,9 +46,8 @@ Iterator := fn($T: type): type {
fold := fn(self: ^Self, $_fold: type, sum: Value): Value {
loop {
x := self.next()
y := self.next()
if y.finished return sum
sum += _fold(x.val, y.val)
if x.finished return sum
sum = _fold(sum, x.val)
}
}
nth := fn(self: ^Self, n: uint): ?Value {
@ -59,6 +58,23 @@ Iterator := fn($T: type): type {
i += 1
}
}
collect := fn(self: ^Self, $A: type): ?A {
if Type(A).kind() != .Array {
@error("unsupported collect (for now)")
}
if @ChildOf(A) != Value {
@error("cannot collect of iterator of type", Value, "into type", A)
}
cont := Type(A).uninit()
i := 0
loop {
defer i += 1
x := self.next()
if i == @lenof(A) & x.finished return cont
if i == @lenof(A) | x.finished return null
cont[i] = x.val
}
}
}
}
@ -114,7 +130,7 @@ Skip := fn($T: type): type {
n := 0
loop {
x := self.iter.next()
if n == self.step return x
if n == self.step | x.finished return x
n += 1
}
}

View file

@ -68,21 +68,20 @@ split_once := fn(haystack: []u8, needle: @Any()): ?struct {left: []u8, right: []
}
}
split := fn(str: []u8, needle: @Any()): Iterator(struct {
$split := fn(str: []u8, needle: @Any()): Iterator(struct {
str: []u8,
needle: @TypeOf(needle),
finished: bool = false,
next := fn(self: ^Self): IterNext([]u8) {
splits := split_once(self.str, self.needle)
if self.finished return .(true, Type([]u8).uninit())
splits := split_once(self.str, self.needle)
if splits != null {
self.str = splits.right
return .(false, splits.left)
} else {
self.finished = true
return .(false, self.str)
}
self.finished = true
return .(false, self.str)
}
}) {
T := @TypeOf(needle)
@ -92,11 +91,11 @@ split := fn(str: []u8, needle: @Any()): Iterator(struct {
return .(.{str, needle})
}
chars := fn(iter: []u8): Iterator(struct {
$chars := fn(iter: []u8): Iterator(struct {
str: []u8,
$next := fn(self: ^Self): IterNext(u8) {
tmp := IterNext(u8).(self.str.len == 0, self.str[0])
tmp := IterNext(u8).(self.str.len == 0, *self.str.ptr)
self.str = self.str[1..]
return tmp
}
@ -104,7 +103,7 @@ chars := fn(iter: []u8): Iterator(struct {
return .(.(iter))
}
chars_ref := fn(iter: []u8): Iterator(struct {
$chars_ref := fn(iter: []u8): Iterator(struct {
str: []u8,
$next := fn(self: ^Self): IterNext(^u8) {

View file

@ -1,15 +1,4 @@
lily := @use("lily/lib.hb")
Allocator := lily.alloc.SimpleAllocator
Vec := lily.collections.Vec
HashMap := lily.collections.HashMap
Random := lily.rand.SimpleRandom
Result := lily.result.Result
Hasher := lily.hash.FoldHasher
$ref_char_to_str := fn(char: ^u8): []u8 {
return char[0..1]
}
lily := @use("lily/lib.hb");
Generator := struct {
n: uint = 0,
@ -22,37 +11,28 @@ Generator := struct {
}
}
$add := fn(lhs: uint, rhs: uint): uint {
return lhs + rhs
$add := fn(sum: uint, x: uint): uint {
return sum + x
}
chars_ref := lily.string.chars_ref
main := fn(argc: uint, argv: []^void): uint {
a := Generator.{}.into_iter().take(50).fold(add, 0)
lily.print(a)
sum := Generator.{}.into_iter().take(50).fold(add, 0)
lily.print(sum)
b := chars_ref("Hello,_").chain(chars_ref("World!")).map(ref_char_to_str).for_each(lily.log.info)
c := chars_ref("Hello,_").intersperse(chars_ref("World!")).map(ref_char_to_str).for_each(lily.log.info)
// ! (libc) (compiler) bug: .collect(T) does not work.
if lily.Target.current() != .LibC {
str := lily.string.chars("Hello, ").intersperse(
lily.string.chars("World!"),
).collect([13]u8)
// allocator := Allocator.new()
// defer allocator.deinit()
// // ! HashMap only works on AbleOS target (due to compiler bugs)
// map := HashMap(uint, uint, Hasher, Allocator).new(&allocator)
// defer map.deinit()
// _ = map.insert(101, 20)
// _ = map.insert(202, 30)
// _ = map.insert(303, 40)
// // ! This iterator only works on AbleOS target (due to compiler bugs)
// map.items().enumerate().for_each(print)
if str != null {
lily.log.info(@as([13]u8, str)[..])
} else {
lily.panic("could not collect (array wrong size)")
}
} else {
lily.log.info("HWeolrllod,! ")
}
return 0
}
// $print := fn(thing: @Any()): void {
// .{n, val: item} := thing
// // ! printf ALSO only works on AbleOS target (due to compiler bugs)
// lily.printf("nth: {}, key: {}, value: {}", .(n, item.key, item.value))
// }
}