In this post, I use the Chain of Responsibility pattern to replace the while loop. The loop itself is done by the composite function defined below. There is another version to composite functions but I found it not easy to debug.
The process will stop when the canContinueF returns false. The result value won't be processed and just slip through other function. The F# provides a good generalization so I do not have to refactor any design pattern code.
let chainTemplate processFunction canContinue s =
if canContinue s then
let composite f a n =
[1..n] |> Seq.map (fun _ -> f) |> Seq.fold (fun acc n -> acc |> n) a
let getReadableSize value =
let unitNames = ["B"; "KB"; "MB"; "GB"; "TB"]
let unit = 1000.
let canContinueF (v,unitNameIndex) = v >= unit && unitNameIndex < unitNames.Length-1
let processF (x, unitNameIndex) = (x / unit, unitNameIndex+1)
let chainFunction = chainTemplate processF canContinueF //combine two functions to get a chainFunction
let (v,i) = composite chainFunction value unitNames.Length //value |> chainFunction |> chainFunction
let (v,name) = getReadableSize (1001000000000000., 0)
printfn "%f %s" (System.Math.Round(v, 2)) name