Я выпил koolaid struct / value в Swift. И вот у меня возникла интересная проблема, которую я не знаю, как решить. У меня есть структура, которая является контейнером, например.
struct Foo {
var bars:[Bar]
}
Внося в него правки, я создаю копии, чтобы сохранить стек отмены. Все идет нормально. Как показали хорошие уроки. Однако есть некоторые производные атрибуты, которые я использую с этим парнем:
struct Foo {
var bars:[Bar]
var derivedValue:Int {
...
}
}
В недавнем профилировании я заметил: а) что вычисления для вычисления производного значения являются своего рода дорогостоящими / избыточными б) не всегда необходимы для вычислений в различных случаях использования.
В моем классическом способе ООП я бы сделал это мемоизирующей / ленивой переменной. По сути, пусть он будет равен нулю, пока он не будет вызван, вычислить его один раз, сохранить его и вернуть указанный результат при будущих вызовах. Поскольку я следую шаблону «копировать для редактирования», инвариант не будет нарушен.
Но я не могу понять, как применить этот шаблон, если он структурный. Я могу сделать это:
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
}
который работает, пока структура не ссылается на это значение, например
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
fun anotherDerivedComputation() {
return self.derivedValue / 2
}
}
На этом этапе компилятор жалуется, потому что anotherDerivedComputation
вызывает изменение в приемнике и, следовательно, должен быть помечен как mutating
. Кажется неправильным помечать аксессуар как изменяющийся. Но что касается ухмылки, я пробую, но это создает новую массу проблем. Теперь везде, где у меня есть выражение вроде
XCTAssertEqaul(foo.anotherDerivedComputation(), 20)
компилятор жалуется, потому что параметр неявно является неизменяемым значением let, а не var.
Есть ли шаблон, который мне не хватает для структуры с отложенным / ленивым / кешированным членом?