[ann] Iterator framework for Pharo

Hello,

I wanted to have an iterator framework for Pharo for a long time.
So I started building it step by step and today I think that, while it still requires more documentation, it is ready to be announced and used by others.
The idea is that, as described by the iterator design pattern, any object that needs to be walked provides one or many iterators.
In the library, #iterator method is the convention to get the default iterator of any object (if it has one).
Iterators provides a DSL to deal with iterators combination.
It is inspired from shell’s streams manipulation syntax:
– The pipe “|” allows one to chain iterators
– The “>” allows one to create a new collection with data transformed through chained iterators
– The “>>” allows one to fill an existing collection with data transformed through chained iterators
For example, one can write:
iterator := #(1 2 3) iterator.
iterator
| [ 😡 | x * 2 ] collectIt
| [ 😡 :y | x + y ] reduceIt
> Array “#(12)”
Or
iterator := #(1 2 3) iterator.
collectionToFill := OrderedCollection new.
iterator
| [ 😡 | x * 2 ] collectIt
| [ 😡 :y | x + y ] reduceIt
> collectionToFill.
collectionToFill “anOrderedCollection(12)”
The equivalent of “/dev/null” in Linux also exists:
iterator := #(1 2 3) iterator.
iterator
| [ 😡 | x * 2 ] collectIt
| [ :object | object logCr ] doIt “Just print incoming objects in transcript.”
> NullAddableObject “Special object that ignore incoming objects.”
There are documentation and examples on the GitHub repository.
Initially, the goal was to avoid to duplicate all collection’s iterator methods (e.g. #collect:, #select:, etc) in composite objects.
Thus, it provides an IteratorWithCollectionAPI which wrap an iterator and provides all the methods we want (#collect:, #select:, …).
Via IteratorWithCollectionAPI, your objects automatically gets the Collection API, you just need to access it via #iterator message:
myObject iterator select: [ 😡 | x isFoo ]
This is another way to use the framework, just to avoid code duplication.
Future work is to provide the possibility to have iterator with multiple inputs.
I already have an undocumented prototype on the repository that works like this:
it1 := (1 to: 10) iterator.
it2 := (1 to: 10) iterator.
it1 & it2
| [ 😡 :y | x@y ] mergeIt
> Array. “{(1@1). (2@2). (3@3). (4@4). (5@5). (6@6). (7@7). (8@8). (9@9). (10@10)}”
Yes, “&” operator will again kind of mimic the one from the shell.
Hope it helps other people.
Feedback is welcome.
Cheers,
Julien
Advertisements
Advertisements
%d bloggers like this: