[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