Reputation: 12107
I have a common pattern:
type something =
{
... a lot of stuff
}
member this.Description =
"a string description of the content, can be long tables, etc"
I would like the Description property to be evaluated ONLY when I need it; in many cases, it won't be used, but it could (mostly on a user's request).
I noticed that this code will cause Description to be evaluated even when it is not needed. So I moved the code to a function: Describe () and it solves the problem.
As I'm refactoring, I'm revisiting this. And while it won't make anything better in practice, I was wondering if something like:
member this.Describe =
(lazy "the long to build text output").Value
would solve the problem? because the lazy object will be created, but nothing may query the value itself.
Would that work reliably?
Upvotes: 2
Views: 115
Reputation: 80744
The way you're declaring the property, it's essentially a function. It doesn't have any parameters, but the code in its body is executed every time somebody tries to read its value. This is how properties work in .NET in general.
This means that whatever you put inside of it, would still execute on every access. Try this:
type T() =
member this.Y =
printfn "Accessing value of Y"
42
let t = T()
let a = t.Y
let b = t.Y
let c = t.Y
You should see "Accessing value of Y" printed out three times.
And it doesn't matter if you wrap the whole thing in lazy
: you're still constructing a brand new Lazy
object on every access to the property, then immediately reading its value, thus causing its body to evaluate.
If you really want to (1) defer evaluation until required and/or (2) cache evaluated value, you should create the Lazy
object outside of the property's body, and then have the property read its value, so that it's the same Lazy
object being read on every property access:
type T() =
let x = lazy (
printfn "Calculating value of X"
"expensive computation"
)
member this.X = x.Value
let t = T()
let a = t.X
let b = t.X
let c = t.X
This will print "Calculating value of X" only once.
Upvotes: 8