I just pushed a rather different version of the iter library to master. The existing approach wasn't really working out. The new one is simpler, and I think it will work out quite well, especially as we start making better use of slices. It is also plays nicely with the `for` loop syntax. Lemme know what you think.

To implement an iterable type, you have to implement this interface:

    iface base_iter<A> {
        // invoke f() on each item, stopping if it returns false
        fn each(f: fn(A) -> bool);

        // returns the number of items in your collection, if you know it,
        // or none otherwise.
        fn size_hint() -> option<uint>;
    }

There are then a variety of various helper methods that you get "for free" (to_vec(), foldl(), contains(), map_to_vec() and so forth). Unfortunately, since we don't have traits, I have to resort to a clever trick that Brian came up with to share these methods. I have defined two instances so far: vec and option. If you want to see how to implement such a type, check out iter-trait.rs and iter-trait/vec.rs. The magic also relies on various #[path] attributes in core.rc. It's deep voodoo, let me tell you.

## Future plans

Later, I would like to add str, map, and a variety of other types. For types (like str and map) where there are multiple possibilities for how to iterate, my plan is to use wrapper types like so:

    enum keys<K,V,M:map<K,V>> = &M;

This wrapper would allow you to iterate over the keys in a map. You would use it something like:

    for keys(&map).each { |k| ... }

This also allows things like

     keys(&map).map_to_vec { |k| ... }

Another example where I think such wrapper types would be helpful is for iterating over two slices in parallel. I planned to have an enum like:

    enum zip<A,B> {
        zip([A]/&, [B]/&)
    }

which would implement the iterable interface for the type (&A, &B). And so forth.

I also wanted to replace (or supplement) the `eachi()` method with something like

    enum enumerate<A,IA:iterable<A>> = IA;

where `enumerate` implements the iface for the type `(uint, IA)`. This would then allow you to write:

    for enumerate(keys(&map)).each { |(i, k)| ... }

(This requires support for irrefutable patterns in argument types, but we should add those)

## Possible far future plans

If we added support for higher-kinded types, we could support a `map()` method in the iteration trait. But until then we have `map_to_vec()`, which always results in a type of `[A]`. Maybe we should find a shorter name, to just do `iterable.to_vec().map()`. I dunno.


Niko
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to