I need an implementation of defaultArg
function with Lazy
as second parameter. Here is a usage example:
defaultArgLazy option (lazy doSomeHeavyWorkThatShouldBeAvoided())
It's quite easy to implement
let defaultArgLazy o (p:'a Lazy) =
match o with
| Some v -> v
| None -> p.Force()
But I wonder if there is a standard implementation that I'm missing.
I don't know of anything built in, but here's a more general version of your function:
module Option =
let lazyDefault f opt =
match opt with
| Some x -> x
| None -> f()
let lazyVal = lazy 1
let opt = None
opt |> Option.lazyDefault lazyVal.Force // returns 1
It takes any function of (unit -> 'a)
instead of specifically a Lazy<'a>'
, so you just pass through Lazy's Force
method instead, and retain the guarantee that the evaluation only happens once.
Perhaps Lazy.Force()
was added in F# on top of .NET's existing Lazy.Value
so that you could use it more idiomatically with higher order functions.
Note that I have swapped the parameter order compared to the built-in defaultArg
to be more consistent with functions in other modules and more convenient for piping/currying.
If the lazy value is only used at a later point in code, it might also be an idea to use defaultArg
and pass it a Lazy<'a> option
as a first argument. That way choosing the option or the default argument is separated from when the result is evaluated.
Taking this idea, the function
let defaultArgLazy opt lazyDef =
(defaultArg (Option.map Lazy.CreateFromValue opt) lazyDef).Value
would do what you want - as does the one by TheQuickBrownFox.
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