On 23. 8. 2019 16:14, Julien wrote:
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.
I present you Iterators : https://github.com/juliendelplanque/Iterators
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 | x * 2 ] collectIt
| [ :x :y | x + y ] reduceIt
> Array "#(12)"
Isn't this something readStream should provide?
str := #(1 2 3) readStream.
str
| [ :x | x * 2 ] collectIt
| [ :x :y | x + y ] reduceIt
> Array "#(12)"
It is an object from which you take the front element, one at a time.
Why have something very similar with different name?
Herby
Or
iterator := #(1 2 3) iterator.
collectionToFill := OrderedCollection new.
iterator
| [ :x | x * 2 ] collectIt
| [ :x :y | x + y ] reduceIt
> collectionToFill.
collectionToFill "anOrderedCollection(12)"
The equivalent of "/dev/null" in Linux also exists:
iterator := #(1 2 3) iterator.
iterator
| [ :x | 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 | 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
| [ :x :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
---
Julien Delplanque
Doctorant à l’Université de Lille
http://juliendelplanque.be/phd.html
Equipe Rmod, Inria
Bâtiment B 40, Avenue Halley 59650 Villeneuve d'Ascq
Numéro de téléphone: +333 59 35 86 40