Are Lazy Vars in Swift Computed More Than Once

Swift Lazy Variables that Load more than Once (Computed Properties?)

You can create something similar to the Objective-C method using a computed property backed by an optional variable.

var _fetchedResultsController: NSFetchedResultsController?

var fetchedResultsController: NSFetchedResultsController {
get {
if _fetchedResultsController != nil {
return _fetchedResultsController!
}
//create the fetched results controller...
return _fetchedResultsController!
}
}

Swift function vs lazy var vs computed property - difference?

  • lazy vars are actually stored properties, so you can't put it in extensions or anywhere stored properties are not allowed.
  • The getter for computed properties is run every time you refer to that property. This can be significant especially if the getter is time-consuming or has side-effects to other parts of the code.
  • The getter for lazy vars are only run when the property is first referred to and never again.
  • lazy vars are variables. You can mutate them.
  • Computed properties can optionally have a setter, so sometimes they are read-only.
  • Using a function like that is very similar to a read only computed property. You just have to add () when getting its value.

What are the potential repercussions of a lazy property getting initialised more than once?

(See my comment to rmaddy's answer regarding my concern about thread-safety on writing the pointer itself. My gut is that memory corruption is not possible, but that object duplication is. But I can't prove so far from the documentation that memory corruption isn't possible.)

Object duplication is a major concern IMO if the lazy var has reference semantics. Two racing threads can get different instances:

  • Thread 1 begins to initialize (object A)
  • Thread 2 begins to initialize (object B)
  • Thread 1 assigns A to var and returns A to caller
  • Thread 2 assigns B to var and returns B to caller

This means that thread 1 and thread 2 have different instances. That definitely could be a problem if they are expecting to have the same instance. If the type has value semantics, then this shouldn't matter (that being the point of value semantics). But if it has reference semantics, then this very likely be a problem.

IMO, lazy should always be avoided if multi-threaded callers are possible. It throws uncertainty into what thread the object construction will occur on, and the last thing you want in a thread-safe object is uncertainty about what thread code will run on.

Personally I've rarely seen good use cases for lazy except for where you need to pass self in the initializer of one of your own properties. (Even then, I typically use ! types rather than lazy.) In this way, lazy is really just a kludgy work-around a Swift init headache that I wish we could solve another way, and do away with lazy, which IMO has the same "doesn't quite deliver what it promises, and so you probably have to write your own version anyway" problem as @atomic in ObjC.

The concept of "lazy initialization" is only useful if the type in question is both very expensive to construct, and unlikely to ever be used. If the variable is actually used at some point, it's slower and has less deterministic performance to make it lazy, plus it forces you to make it var when it is most often readonly.

Swift: why lazy, computed property, and property observer can not be let

Lazy properties : You must always declare a lazy property as a variable (with the var keyword), because its initial value might not be retrieved until after instance initialization completes. Constant properties must always have a value before initialization completes, and therefore cannot be declared as lazy.

computed property : whereas computed properties calculate (rather than store) a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly.

property observer : property observers is to monitor changes in a property’s value, if you define it let then how you can monitor changes because let is one type of constant which you can not change after init.

Why lazy variables / computed properties, not just methods

Answer: Lazy variables exist to cut on loading time (i.e. for optimization reasons). Some variables aren't needed immediately unless explicitly called for. And they, like Math.pi might take a while to compute. So the application may start computing them in a background thread when the most important user-initiated operations have finished.

As for computed properties, I think it's more of a language decision. Objective-C introduced properties a long time ago, and they've always been technically 'computed' (with getters and setters, be it automatically synthesized / explicitly implemented), and it was (and is) a wildly accepted feature. Why? I don't know for sure. Maybe there isn't 'one clear answer' to this question. Like I said, I believe it's a language decision, not something that can be rationalized completely.

For me personally, it feels more intuitive to both read and write a property using the same .property syntax, rather than property() and setProperty(_: Property) functions. This is an abstraction, and language abstractions exist for comfort / ease-of-use. Your examples are highly contrived, and computed properties are used by the thousands across Apple's frameworks. Not each computed property needs to be extremely time consuming, and most of them are in fact practically instant; thus they are abstracted to feel so.

When you think about it, everything is technically computed. Even if you, for example, set an integer value directly to a structure field, there are things that need to happen on a lower scale. These low level computations are abstracted to feel like non-computed, concrete entities, when in reality they are. It all boils down to abstraction.

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

If global properties are always computed lazily, and local properties are never, what does the lazy modifier modify?

"Local constants and variables" in that provided excerpt refer to local scope constants and variables, as in local variables of a function. They do not refer to properties of objects, which can be lazy, if they are marked with the lazy keyword.

//global, declared outside of a class/struct
//error is "Lazy is only valid for members of a struct or class
lazy var label: UILabel = {
var tempLabel: UILabel = UILabel()
tempLabel.text = "hi"
return tempLabel
}()

class SomeClass : NSObject {
//non-lazy instance property
var x = 3

//lazy instance property
lazy var label: UILabel = {
var tempLabel: UILabel = UILabel()
tempLabel.text = "hi"
return tempLabel
}()


func doStuff() {
//error is "Lazy is only valid for members of a struct or class
lazy var label: UILabel = {
var tempLabel: UILabel = UILabel()
tempLabel.text = "hi"
return tempLabel
}()
}
}

Lazy Var vs Let

This is the latest scripture from the Xcode 6.3 Beta / Swift 1.2 release notes:

let constants have been generalized to no longer require immediate
initialization. The new rule is that a let constant must be
initialized before use (like a var), and that it may only be
initialized: not reassigned or mutated after initialization.

This enables patterns like:

let x: SomeThing
if condition {
x = foo()
} else {
x = bar()
}

use(x)

which formerly required the use of a var, even though there is no
mutation taking place. (16181314)

Evidently you were not the only person frustrated by this.



Related Topics



Leave a reply



Submit