In an online discussion, when Java 8 released their stream API, written about here, you can write e.g.
Composable in this context means: To be able to compose two things into one without redundancy or overhead. For example, consider you want to map a function
f over an array
arr to produce a new array, you might do this:
If you want to filter the array based on a predicate
p, you might do this:
Or maybe you want to take all elements until a a predicate
p2 is not satisfied:
Now, if you want to do that all in one process you have a few options:
takeWhile()and then write
arr.map(f).filter(p).takeWhile(p2). Good abstraction, very low maintenance because the functions are black boxes. But inefficient.
An ideal stream API will give you the last point, but be able to understand concepts like mapping and filtering and know how to merge them together into an efficient loop. This is called stream fusion, which you can google if you want to know more.
I don’t know Java but I can give a Haskell example:
(Note: In Haskell the operations separated by
. are run right to left, like
map f (filter p (takeWhile p2 …)).)
If I compile this with GHC, e.g.
and look at the reduced output called Core, a language the compiler generates code for before generating assembly or byte code, the
map f . filter p are both compiled into a single loop (Core output is verbose, so I collapsed it into this more readable form). This just walks over the list, checks whether the item is even, if so, keeps it and adds 2 to it, otherwise skips that item:
Which is pretty nifty. Furthermore, if you fold (also called reducing) e.g.
Then that whole thing is also compiled into one loop:
There’re limits to what can compose with what, though.