[swift-evolution] lazy keyword vs lazy initialization pattern
Cole Kurkowski
crk at fastmail.com
Fri Dec 4 13:16:43 CST 2015
To me this actually feels more like something that might fit better as an additional type of optional, rather than a language feature.
Setting this optional to nil could work normally, and any attempt to access the value when nil would cause the reload to occur. The initialization semantics might be a tad ugly though.
var myLazyOpt = ReloadingOptional<ForeignClass>({
return Database.expensiveSelect(self.foreignKey)
})
You could probably implement something like this yourself, though I'm not sure how elegant that would be without full language support.
Thanks for your time,
Cole Kurkowski
> On Dec 4, 2015, at 07:40, David Hart <david at hartbit.com> wrote:
>
> In Objective-C, I often used the lazy initialization pattern to implement a cache for expensive operations. For exemple, here is an often used scenario in a project where objects behind foreign keys in a database ORM are only fetched when necessary:
>
> @interface MyClass : NSObject
>
> @property (nonatomic) ForeignClass* foreignObject;
> @property (nonatomic) int64_t foreignKey;
>
> @end
>
> @implementation MyClass
>
> - (void)setForeignKey:(int64_t)foreignKey {
> _foreignKey = foreignKey;
> _foreignObject = nil;
> }
>
> - (ForeignClass*)foreignObject {
> if (!_foreignObject) {
> _foreignObject = [Database expensiveSelect:_foreignKey];
> }
> return _foreignObject;
> }
>
> @end
>
> Unfortunately, the lazy keyword in Swift, which was supposed to make the lazy initialization pattern more concsive does not work in this case:
>
> class MyClass {
> var foreignKey: Int64 {
> didSet {
> self.foreignObject = nil
> }
> }
>
> lazy var foreignObject: ForeignClass? = {
> return Database.expensiveSelect(self.foreignKey)
> }()
> }
>
> I'm forced to rewrite it this way:
>
> class MyClass {
> var foreignKey: Int64 {
> didSet {
> self.foreignObject = nil
> }
> }
>
> private var _foreignObject: ForeignClass? = nil
> var foreignObject: ForeignClass? {
> if _foreignObject == nil {
> _foreignObject = Database.expensiveSelect(self.foreignKey)
> }
> return _foreignObject
> }
> }
>
> When thinking about it, I came to the conclusion that the use cases of lazy seem very narrow compared to how useful the lazy initialization pattern was in Objective-C.
> I want your opinion on three alternatives:
>
> 1- Do nothing, and use the slightly uglier Swift example when using a cache.
> 2- Modify lazy semantics to re-calculates when nil (I think this is the worst solution).
> 3- Add a cache modifier that re-calcualtes when nil.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list