包含惰性元素的数组

时间:2017-01-22 09:28:52

标签: arrays swift lazy-initialization

我想知道Swift 3编程语言中是否有一个构造允许我将一些对象存储在一个数组中,但是懒惰地初始化该数组中的每个元素。

想象一下这个示例类:

class A {
    let test = "hello"
    let test2 = 2.0
}

现在我想存储一个' A'另一个类的数组中的对象,如下所示:

class B {
    var lazy(?) array: [A] = {
        // Some code to initialize the element being accessed
    }()
}

如果我现在访问任何元素,如果在我访问它时初始化它会很酷,所以很懒散

print(B.array[1].test) (element at index one is now initialized)

这可能吗?

2 个答案:

答案 0 :(得分:2)

您可以使用lazy支持A后备存储,该存储在首次访问时实例化,例如:

class Astorage {
    /* ... lots of ... */
    let id: Int
    var foo: String = "bar"
    init(_ id: Int) {
        self.id = id
        print("Initializing backing storage for A with id \(id)")
        // ...
    }
}

class A {
    private let id: Int
    lazy var storage: Astorage = Astorage(self.id)
    init(_ id: Int) {
        self.id = id
    }
}

class B {
    var array: [A]
    init (_ array: [A]) {
        self.array = array
    }
}

let b = B((1...5).map(A.init))

b.array[2].storage.foo = "foo"
// Initializing backing storage for A with id 3

b.array[4].storage.foo = "bax"
// Initializing backing storage for A with id 5

答案 1 :(得分:2)

您可以使用enummutating struct来实现此目标

enum LazyValueEnum<T>: CustomStringConvertible {
    case value(T)
    case thunk((Void) -> T)

    var forceValue: T {
        switch self {
        case .value(let t):
                return t
        case .thunk(let thunk):
                return thunk()
        }
    }

    var description: String {
        switch self {
        case .value(let t):
            return String(describing: t)
        case .thunk(_):
            return "<thunk>"
        }
    }
}

struct LazyValue<T>: CustomStringConvertible {

    var value: LazyValueEnum<T>

    init(_ t: T) {
        self.value = .value(t)
    }

    init(lazy thunk: @escaping (Void) -> T) {
        self.value = .thunk(thunk)
    }

    static func lazy(_ thunk: @escaping (Void) -> T) -> LazyValue<T> {
        return LazyValue(lazy: thunk)
    }

    static func value(_ value: T) -> LazyValue<T> {
        return LazyValue(value)
    }

    mutating func forceValue() -> T {
        let t = value.forceValue
        value = .value(t)
        return t
    }

    var description: String {
        return value.description
    }
}


var a: [LazyValue<Int>] = [.value(5), .value(7), .lazy { Int(arc4random()) }]
print(a)
print(a[2].forceValue())
print(a)
print(a[2].forceValue())
print(a)

游乐场的结果: enter image description here