I want to write a chain of transformations and finally have a block where I do something with the resulting collection, without using variables. Is there a higher-order function on collections that just provides the collection on which it is called to the supplied function?
Query( ... )
.map { ... }
.filter { ... }
.combinations(2)
.pipeTo { col =>
...
consolidate(col)
}
Of course for a single function call one could do it like this:
consolidate(
Query()
.map { ... }
.filter { ... }
.combinations(2)
)
But the former reads more natural to me and allows e.g. for an easy injection of some conditionals.
A workaround I've been using is placing a match clause at the end:
Query()
.map { ... }
.filter { ... }
.combinations(2)
match { case lst =>
...
consolidate(lst)
}
But since this pattern occurs quite often I was wondering what is the idiomatic way to write this.
Perhaps the most idiomatic way would be to use the so called Pimp My Library Pattern, which allows one to add extension methods to any classes via implicit class conversions.
For example, to add a
consolidate
method toList
s, you could write:If you really want to be able to call arbitrary functions on arbitrary objects in a chain, you could even define an "pipeline" operator like in F#:
The
|>
operator behaves like thepipeTo
method you have defined.Basically, this works by creating an implicit conversion from your type to the type with the various extension methods that you define. The
AnyVal
makes the extension class an value class, so its use will have little to no runtime cost.