Skip to content

Instantly share code, notes, and snippets.

@ezura
Created July 1, 2017 01:28
Show Gist options
  • Select an option

  • Save ezura/28194c059a292dcdade35d00fbe21dfe to your computer and use it in GitHub Desktop.

Select an option

Save ezura/28194c059a292dcdade35d00fbe21dfe to your computer and use it in GitHub Desktop.
kotlin の lazy を真似て実装
import Foundation
// I could not nest in `Lazy<T>` :(
// to handle Optional
private enum Value<T> {
case uninitialized
case initialized(T)
}
class Lazy<T> {
private let initializer: () -> T
private var _value: Value<T> = .uninitialized
var value: T {
get {
// TODO: mutex
switch _value {
case .uninitialized:
let instance = initializer()
_value = .initialized(instance)
return instance
case .initialized(let v):
return v
}
}
set {
_value = .initialized(newValue)
}
}
init(initializer: @escaping () -> T) {
self.initializer = initializer
}
/*
to call `inctance[]`
compromise 😇
*/
subscript(v: Void) -> T {
get { return value }
set { self.value = newValue }
}
}
func lazy<T>(initializer: @escaping () -> T) -> Lazy<T> {
return Lazy(initializer: initializer)
}
struct A {
init() { print("call `A.init`") }
}
class B {
var v1 = lazy { return A() } // ❗️self making
lazy var v2 = { return A() }() // swift's `lazy`
}
let b = B()
print("will call `B.v1`", #line)
b.v1[] // A()
print("will call `B.v1`", #line)
b.v1[] // A()
print("will call `B.v1`", #line)
b.v1[] // A()
print()
print("will call `B.v2`", #line)
b.v2 // A()
print("will call `B.v2`", #line)
b.v2 // A()
print("will call `B.v2`", #line)
b.v2 // A()
/* ## output
will call `B.v1` 59
call `A.init` <- ❗️call `init` once
will call `B.v1` 61
will call `B.v1` 63
will call `B.v2` 66
call `A.init` <- ❗️call `init` once
will call `B.v2` 68
will call `B.v2` 70
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment