Composing functions and leveraging scala.util.Try
Last couple of days I have been hacking around trying to find a cute way to express the intent of my code. Typically it involves parsing some input, validating whatever rules that are in charge and persisting some values. In scala one can compose such a function by using the andThen method. Here is a concrete example:
def id(x: String) = x
def parseInput = id _
def validate = id _
def persist = id _
def usecase1 = parseInput andThen validate andThen persist
Inspired by the excellent series on Railway Oriented Programming series by Scott Wlaschin I wanted to take advange of scala.util.Try to remove try/catch clutter from my code. With a little helper function I can now compose my usecase as following:
def makeTry[TIn, TOut](fn: TIn => TOut) = (x: TIn) => Try(fn(x))
def usecase =
makeTry(parseInput andThen validate andThen persist) andThen
processErrors andThen
proceedOrRetry
Instead of composing functions I could have also written code as a chain of values that are transformed by subsequent functions as following (Very much fsharp like):
class Pipe[T](val x: T) {
def |> [U](f: T => U) = f(x)
}
implicit def toPipe[T](x: T) = new Pipe(x)
def usecase(x: String) =
Try(x |> parseInput |> validate |> persist) |>
processErrors |>
proceedOrRetry
As you can see, with scala there is more than one way to express something in an elegant way!