How do we represent that there's no answer? Let's use an array so it may or may not have an element in it.
mapfollowed by a
flatten(1)is a common pattern so it actually has its own combined operation:
flat_mapmultiple values to perform computations upon?
mapwould collect into the output each array of each computation step, empty or otherwise. You can think of
flat_mapas concatenating each step's result to the final output array 'flatly' rather than creating nested array elements. Concatenating an empty array has no effect so does not appear in the final output.
Gemfilewith the following contents:
[-1].mapwith a block that returns numbers.
Optional.none.and_thennever entered the block and merely returned
maybe_rootas we defined it here would be a
maybe_whole_rootwhich only returns roots if the input is a square value. Then if the computation on the value
2does not return a whole number, further chained computations will continue to return
Optionalwhich can be used with this behaviour. Using an array with a chain of
flat_mapoperations has a similar effect.
Optionalwith the added benefit that when there's no value, the reason for the missing value can be stored and later retrieved.
Aand a function that can turn any instance of
Mis some context such as
Async, etc, then we can chain computations together using these function without examining or adapting their shapes in-between.
Mare called Monads in Category Theory. Not only can you chain computations within the same context, you can compose contexts, e.g.
M1[M2[M3[A]]]with each context handling a different computational aspect or concern. Some examples would be configuration, logging, generating metrics, sending notifications, and the list is quite endless when decomposing problems this way. In a highly-typed language, the type itself identifies the computations that exactly will have had to occurred (or at least attempted) to produce a value of the type.