This is a really interesting question. Here I have a few different ideas that could help.
First, you are slightly abusing the idea of a lazy property. You may have lazy stored properties , because all that is lazy is the execution of the delay until it is first run. This value is then stored in the property next. You are dealing with a computed property that cannot be used in this way. You can, of course, file a radar, but I think this is a lost reason, because your use case is not a valid IMO lazy case.
With that said, I think you have several options.
Option 1 - Using a Class with Property Observers
class Calculator { var value: Int { didSet { valueChanged = true } } var valueChanged = false var derivedValue: Int { if valueChanged { println("Doing expensive calculation") valueChanged = false } return self.value * 2 } init(value: Int) { self.value = value } func mutate() { value = random() } }
The advantage is that you can still lazily compute derivedValue at the point at which the property is called. The disadvantage is that you no longer use the "by value" object.
Option 2 - Calculation of the Value in the Mutate Method
struct SortOfLazyCalculator { var value: Int var expensiveComputedValue: Int = 0
The advantage of this approach is that you can still save your object "by value", but you need to calculate an expensive value during the mutation. You cannot do this inside the derivedValue property, because you cannot mutate self inside the computed property for the structure.
Option 3 - Using Static Struct to Track Value Changes
struct Struct { var value: Int var derivedValue: Int { struct Static { static var previousValue: Int? } if Static.previousValue == nil { println("Setting previous value since it is nil") Static.previousValue = value } if value != Static.previousValue! { println("Doing expensive calculation") Static.previousValue = value } return self.value * 2 } init(value: Int) { self.value = value } mutating func mutate() { value = random() } }
This approach allows you to save the object "by value", and also allows you to lazily calculate an expensive value. However, the main problem is that this will only work for one object. If you create multiple objects, this is a bad approach.
Summary
Unfortunately, this is an invalid use case for a lazy property. However, there are other approaches to solving this problem. I hope one of them will be enough. Based on all the information you provided, I would venture to suggest that Option 2 is probably the best choice.