-
-
Notifications
You must be signed in to change notification settings - Fork 312
Open
Description
While it is currently possible to create objects that support the foreach statement by implementing .len and [], some objects that would typically be iterated through may not have a definite value to return for .len or [].
Having the following as standard interfaces:
module iter { Type1 };
interface Iterator {
fn bool next(Type1* out);
}
interface Iterable {
fn Iterator{Type1} new_iterator(Allocator a);
fn Iterator{Type1} tnew_iterator();
}
macro Iterator.@foreach(&self; @block(elem)) {
Type1 elem;
while(self.next(&elem)) {
@block(elem);
}
}
macro Iterable.@foreach(&self; @block(elem)) {
@pool() {
Iterator iter = self.tnew_iterator();
Type1 elem;
while(iter.next(&elem)) {
@block(elem);
}
};
}This would open the door to "generator" types, for example a sequence of all prime numbers up to a specific value:
// new and free not shown for simplicity
struct PrimeIterator (Iterator{uint}) {
// initialized to 2
uint current;
uint limit;
List { uint }* seen;
}
fn bool PrimeIterator.next(&self, uint* out) @dynamic {
while(self.current < self.limit) {
bool is_prime = true;
foreach(i, v : self.seen) {
if(self.current % v != 0) { continue; }
is_prime = false;
break;
}
if(!is_prime) {
self.current += 2; // Always go to next odd number
continue;
}
*out = self.current;
if(self.current == 2) { self.current += 1; } // special case to go from 2 to 3
else { self.current += 2; } // can iterate only odds after 3
return true;
}
return false;
}It would also ensure that types like linked list could iterate their nodes in a more performant way, since they would be able to step node to node, rather than needing to do a full [n] lookup through all n nodes.
Metadata
Metadata
Assignees
Labels
No labels