Протокол Swift с ленивым свойством - невозможно использовать изменяющий метод get для неизменяемого значения: «$ 0» является неизменным - PullRequest
2 голосов
/ 13 октября 2019

Цель: создать протокол, который позволяет ленивое вычисление свойства для структур, которые соответствуют протоколу, а затем добавить свойства для массива этих структур. Вычисления интенсивны и должны выполняться только один раз, отсюда и требование lazy.

Итак, после большого чтения (например: Swift Struct с Lazy, частная собственность соответствует протоколу ) и проб и ошибок (пожалуйста, не отмечайте это как дубликат, если толькона самом деле решает именно этот случай), я придумал что-то, что работает:

import Foundation

protocol Foo {
    var footype: Double { mutating get }

    func calculateFoo() -> Double
}

struct Bar: Foo {
    private lazy var _footype: Double = {
        let value = calculateFoo()

        return value
    }()

    var footype: Double {
        mutating get {
            return _footype
        }
    }

    func calculateFoo() -> Double {
        print("calc")
        return 3.453
    }
}

Тестирование на игровой площадке:

var bar = Bar()
print(bar.footype)
print(bar.footype)

И вывод:

calc
3.453
3.453

Пока все хорошо.

Теперь я хочу создать массив из Bar и добавить свойства footype:

var bar1 = Bar()
var bar2 = Bar()
var bar3 = Bar()
var bars = [bar1, bar2, bar3]

print(bars.map { $0.footype }.reduce(0.0, +))

, что дает мне следующую ошибку:

Невозможно использовать изменяющий метод получения неизменяемого значения: '$ 0' является неизменным

Обнаружено много информации об этой ошибке, но я не могу ее решить. Одним из способов было бы использовать class вместо struct, но это не работает с другими частями кода.

Возможно ли то, что я пытаюсь достичь?

1 Ответ

4 голосов
/ 13 октября 2019

Как вы можете сказать из сообщения об ошибке, $0 является неизменным, поэтому вы не можете использовать мутирующий член для него.

Следовательно, вы не можете перебирать bars напрямую. То, что вы можете сделать, это перебрать его indices, потому что мы знаем, что bars[$0] является изменяемым:

print(bars.indices.map { bars[$0].footype }.reduce(0.0, +))
...