Hi This is supercool!
I had been wondering myself of the lack of such a library. The Xtreams seem to be a bit related, but they focus on IO more that map/reduce programming. I am intrigued by your choice of argument-less methods (reduceIt, collectIt,…). I would most likely have opted for a syntax in the style of ((iterator collect: […]) select: […]) groupBy: [..] etc Your syntax do away with the parenthesis hell. I like that aspect. Do you see a connection to the database query (linq like) thing, working towards the same api for the iterators and queries ? Going that direction might also enable some more advanced ideas for the & operator (more akin to join). Cool stuff Julien! Best, Kasper On 23 August 2019 at 16.15.31, Julien (julien.delplan...@inria.fr) 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)" 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