What Is The Advantage of Closure Stored Property Initialisation

Difference between computed property and property set with closure

In short, the first is a stored property that is initialized via a closure, with that closure being called only one time, when it is initialized. The second is a computed property whose get block is called every time you reference that property.


The stored property’s initialization closure is called once and only once, but you can later change the value of the stored property (unless you replace var with let). This is useful when you want to encapsulate the code to initialize a stored property in a single, concise block of code.

The computed property’s block, however, is called each time you reference the variable. It’s useful when you want the code to be called every time you reference the computed property. Generally you do this when the computed property needs to be recalculated every time you reference the stored property (e.g. recalculated from other, possibly private, stored properties).

In this case, you undoubtedly want the stored property (the first example), not the computed property (the second example). You presumably don't want a new push behavior object each time you reference the variable.


By the way, in your first example, you internally reference to it being instantiated lazily. If you want that behavior, you must use the lazy keyword:

lazy var pushBehavior: UIPushBehavior = {
let behavior = UIPushBehavior()
behavior.setAngle(50, magnitude: 50)
return behavior
}()

If, however, the property is static, it is automatically instantiated lazily.

What is the advantage of a lazy var in Swift

Lazy Stored Property vs Stored Property

There are a few advantages in having a lazy property instead of a stored property.

  1. The closure associated to the lazy property is executed only if you read that property. So if for some reason that property is not used (maybe because of some decision of the user) you avoid unnecessary allocation and computation.
  2. You can populate a lazy property with the value of a stored property.
  3. You can use self inside the closure of a lazy property

When isn't necessary to initialize lazy variable with lambda execution?

People who do it the second way are making a mistake, that’s all.

The mistake is an easy one. Sometimes (1) a define-and-call initializer is necessary, namely when you need multiple code statements to obtain the initial value of a variable:

let timed : Bool = {
if val == 1 {
return true
} else {
return false
}
}()

Sometimes (2) you need lazy initialization, namely in order to mention self during property initialization:

lazy var arrow : UIImage = self.arrowImage()

And sometimes (3) you need both together to do both things:

lazy var prog : UIProgressView = {
let p = UIProgressView(progressViewStyle: .default)
p.alpha = 0.7
p.trackTintColor = UIColor.clear
p.progressTintColor = UIColor.black
p.frame = CGRect(x:0, y:0, width:self.view.bounds.size.width, height:20)
p.progress = 1.0
return p
}()

So it is natural out of habit, misunderstanding, or abundance of caution to resort to form 3 when in fact there was only one line and all you needed was form 2. It’s an easy mistake and does no harm.

Property initialization using by lazy vs. lateinit

Here are the significant differences between lateinit var and by lazy { ... } delegated property:

  • lazy { ... } delegate can only be used for val properties, whereas lateinit can only be applied to vars, because it can't be compiled to a final field, thus no immutability can be guaranteed;

  • lateinit var has a backing field which stores the value, and by lazy { ... } creates a delegate object in which the value is stored once calculated, stores the reference to the delegate instance in the class object and generates the getter for the property that works with the delegate instance. So if you need the backing field present in the class, use lateinit;

  • In addition to vals, lateinit cannot be used for nullable properties or Java primitive types (this is because of null used for uninitialized value);

  • lateinit var can be initialized from anywhere the object is seen from, e.g. from inside a framework code, and multiple initialization scenarios are possible for different objects of a single class. by lazy { ... }, in turn, defines the only initializer for the property, which can be altered only by overriding the property in a subclass. If you want your property to be initialized from outside in a way probably unknown beforehand, use lateinit.

  • Initialization by lazy { ... } is thread-safe by default and guarantees that the initializer is invoked at most once (but this can be altered by using another lazy overload). In the case of lateinit var, it's up to the user's code to initialize the property correctly in multi-threaded environments.

  • A Lazy instance can be saved, passed around and even used for multiple properties. On contrary, lateinit vars do not store any additional runtime state (only null in the field for uninitialized value).

  • If you hold a reference to an instance of Lazy, isInitialized() allows you to check whether it has already been initialized (and you can obtain such instance with reflection from a delegated property). To check whether a lateinit property has been initialized, you can use property::isInitialized since Kotlin 1.2.

  • A lambda passed to by lazy { ... } may capture references from the context where it is used into its closure.. It will then store the references and release them only once the property has been initialized. This may lead to object hierarchies, such as Android activities, not being released for too long (or ever, if the property remains accessible and is never accessed), so you should be careful about what you use inside the initializer lambda.

Also, there's another way not mentioned in the question: Delegates.notNull(), which is suitable for deferred initialization of non-null properties, including those of Java primitive types.

Swift class: declare variables with closures pointing to member functions

Assigning the value inside the initializer cannot work, since you are trying to assign an instance property (or function in your specific case) to another instance property, but in the initializer, neither of them are guaranteed to be initialized.

You can solve your problem by declaring aFunc as lazy. You won't need an initializer anymore either.

lazy var aFunc: (Int) -> () = f_release

Advantage of computed properties (gettable ones only) vs. stored properties

Computed Properties

var sayGoodMorningToUserComputed: String {
return greeting + username
}

sayGoodMorningToUserComputed acts just like a function. If a change has been made to greeting or username, then sayGoodMorningToUserComputed will return an up-to-date result that will be the concatenation of the current values.

You would want to use this if you want to ensure your returned value is computed off the latest values of its dependencies (greeting and username).

In the case that both dependencies are final, then it's very likely that the compiler would optimise this computed property into a stored property, because it knows the dependencies can't change

Stored properties

var sayGoodMorningToUserStored = greeting + username

sayGoodMorningToUserStored is just a variable, with nothing special going on. However, it's only set once, whenever the containing scope is initialized. It's computed once, stored and remains constant until it is overwritten by an external source. As such, if greeting or username changes, there will be no effect on sayGoodMorningToUserStored, because it's been computed from the old values, and stored.

You would want to use this if you want to improve performance by caching the result of a computation whose dependencies are constant.

How do JavaScript closures work?

A closure is a pairing of:

  1. A function and
  2. A reference to that function's outer scope (lexical environment)

A lexical environment is part of every execution context (stack frame) and is a map between identifiers (i.e. local variable names) and values.

Every function in JavaScript maintains a reference to its outer lexical environment. This reference is used to configure the execution context created when a function is invoked. This reference enables code inside the function to "see" variables declared outside the function, regardless of when and where the function is called.

If a function was called by a function, which in turn was called by another function, then a chain of references to outer lexical environments is created. This chain is called the scope chain.

In the following code, inner forms a closure with the lexical environment of the execution context created when foo is invoked, closing over variable secret: