Skip to content

Instantly share code, notes, and snippets.

@jpmcglone
Last active August 18, 2020 20:41
Show Gist options
  • Save jpmcglone/87883ff281408731256251e32f98ad9c to your computer and use it in GitHub Desktop.
Save jpmcglone/87883ff281408731256251e32f98ad9c to your computer and use it in GitHub Desktop.
@propertyWrapper
class Lazy<T> {
fileprivate var loader: (()->T)
fileprivate var _value: T?
var projectedValue: Lazy<T> { return self }
var wrappedValue: T {
_value = _value ?? loader()
return _value!
}
init(wrappedValue: T) {
_value = wrappedValue
self.loader = { wrappedValue }
}
init(_ loader: @autoclosure @escaping ()->T) {
self.loader = loader
}
init(load loader: @escaping ()->T) {
self.loader = loader
}
func reset() {
_value = nil
}
}
@propertyWrapper
class LazyMutable<T>: Lazy<T> {
override var projectedValue: LazyMutable<T> { return self }
override var wrappedValue: T {
get { super.wrappedValue }
set { set(newValue) }
}
func set(_ loader: @autoclosure @escaping ()->T) {
set(loader)
}
func set(_ loader: @escaping ()->T) {
_value = nil
self.loader = loader
}
}
@jpmcglone
Copy link
Author

jpmcglone commented Dec 31, 2019

Here's a struct approach:

// MARK: - Property Wrappers / Structs
@propertyWrapper
struct Lazy<T> {
  private var loader: (()->T)
  private var _value: T?
  var wrappedValue: T {
    mutating get { get() }
  }

  init(_ loader: @autoclosure @escaping ()->T) {
    self.loader = loader
  }

  init(wrappedValue: T) {
    self.init(wrappedValue)
  }

  mutating func get() -> T {
    _value = _value ?? loader()
    return _value!
  }

  mutating func reset() {
    _value = nil
  }
}

@propertyWrapper
struct LazyMutable<T> {
  private var loader: (()->T)
  private var _value: T?
  var wrappedValue: T {
    mutating get { get() }
    set { set(newValue) }
  }

  init(_ loader: @autoclosure @escaping ()->T) {
    self.loader = loader
  }

  init(wrappedValue: T) {
    self.init(wrappedValue)
  }

  mutating func get() -> T {
    _value = _value ?? loader()
    return _value!
  }

  mutating func set(_ loader: @autoclosure @escaping ()->T) {
    _value = nil
    self.loader = loader
  }

  mutating func reset() {
    _value = nil
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment