Happy !

sydlar / LarsPipes

Project infos

License GPLv3
Tags
Creation date 2017-09-14
Website

Monticello registration

About LarsPipes

For the moment, this is only an outline of the idea behind this project

Basic idea

What if #collect: and #select: were binary operators? Instead of

array collect: firstBlock) select: secondBlock) collect: thirdBlock,

we could then write

array |> firstBlock |? secondBlock |> third block

I believe that it will be practical to introduce binary operators |> and |? (the collect- and select-operator, respectively), such that

  • aCollection |> aBlock gives a stream consisting of the elements in anCollection transformed by aBlock.
  • aStream |> aBlock gives in a similar way a stream.
  • aStream |> aCollection fills the collection with the elements of the stream.

In a similar way, it could be practical to handle individual objects as well as undefined objects with the same operator:

  • nil |> aBlock gives nil (or maybe better an empty stream?).
  • anObject |> aBlcok is synonymous with aBlock value: anObject (or maybe better: an one element stream?)

When it comes to the #select: -operator |? one should of course make similar definitions.

Concatenation of blocks

It would be practical to be able to concatenate blocks, and make pipes that can be used in different contexts: firstBlock |> secondBlock should give an instance of the class Pipe, defined in such a way that

` aCollection |> (firstBlock |> secondBlock)

is equivalent to

aCollection |> firstBlock | secondBlock.

With a similar definition of the #select:-operator |?, one could make general filter-and-transform-objects as

 getMaxInMediumSizedSamples := [ :each | each contents ] 
      |? [ :contents  | contents size > 50 ] 
      |? [ :contents | contents size < 100] 
      |> [ :contents | contents max ]

Once getMaxInMediumSizedSamples is defined, one could use it in various contexts.

Lazy evaluation

When we define the operators |> and |? in such a way that they always produce streams, we get a nice feature for free, namely that nothing is evaluated before we ask for it, for instance

 (aCollection collect: aBlock) detect:  anotherBlock

immediately calls aBlock on all the element of the collection, and then uses detect. On the other hand,

 (aCollection |> aBlock |? anotherBlock) next

only evaluates aBlock until the first element where anotherBlock returns true.

Collectors

We should also define collectors, i.e. objects that can collect the data form a stream, so that we for instance could write

 (1 to: 10) |> [ :x | 2*x -1 ] |> Collector sum               "Gives the sum"
 (1 to: 10) |> [ :x | 2*x -1 ] |> Collector product          "Gives the product"
 (1 to: 10) |> [ :x | 2*x -1 ] |> Collector collect            "Collects object in OrderedCollection"
 (1 to: 10) |> [ :x | 2*x -1 ] |> Collector inject: anObject into: aBlock. "Similar to #inject:into:"