I have two functions that are a composition of pure functions. The first function takes a parcel, builds a house on it, and take a picture to advertise it in a magazine:
let buildAndAdvertiseHouse parcel =
parcel
|> inspect
|> buildWalls
|> buildRoof
|> takePhoto
|> advertise
The second function takes also a parcel, builds a house on it, and adds a finishing touch to it:
let buildAndCompleteHouse parcel =
parcel
|> inspect
|> buildWalls
|> buildRoof
|> paintWalls
|> addFurniture
It's clear that the two functions are also pure, since they are a composition of pure functions. Now I have a parcel, let say niceParcel
and I want to apply both functions to it. However, I want to avoid that the first three sub-functions are calculated twice since they take a big time to compute and they are shared among the two functions.
How do I refactor my code, so these unnecessary calculations are avoided, while keeping these nice pure functions which have a clear meaning?
As others mentioned in the comments, I think the best approach is to turn the common part into a build
function. Even if you do not intend to use the function for other purposes, this is a clean way of structuring functional code.
In F#, you can define a type that represents a partially built house, but does not expose its internals. This means that the callers of your library can use build
to build a partially constructed house, but then the only thing they can do with it is to use the two functions you provided:
module Houses =
type House = private HouseData of <whatever>
let build parcel = (...)
let buildAndAdvertiseHouse house =
house
|> takePhoto
|> advertise
let buildAndCompleteHouse house =
house
|> paintWalls
|> addFurniture
You can hide the fact that one needs to build a house before you can advertise & complete it in various ways. For example, if you typically do both operations at once, then you can define a function that calls all three functions - and the user of your library can either just use this or learn a bit more about house building and use the three functions if they need a finer control.
Another approach would be to just wrap the functionality in a simple type. F# mixed functional and object-oriented style, so there is nothing really wrong with having a type that runs the common part once and keeps some state.
type House(parcel) =
let house =
parcel
|> inspect
|> buildWalls
|> buildRoof
member x.BuildAndAdvertiseHouse()
house
|> takePhoto
|> advertise
member x.BuildAndCompleteHouse() =
house
|> paintWalls
|> addFurniture
This is fine in F#, but I think I would prefer the functional approach with a build
function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With