lazy variable with closure - swift

In this article, it says (referencing the code below): "You must use lazy to prevent the closure for being created more than once."
private lazy var variable:SomeClass = {
let fVariable = SomeClass()
fVariable.value = 10
return fVariable
}()
Why would lazy prevent the closure from being created more than once? And why would the lack of lazy cause it to evaluate more than once?

The tutorial code you quote is this:
private lazy var variable:SomeClass = {
let fVariable = SomeClass()
fVariable.value = 10
return fVariable
}()
Contrast it with this:
private var variable:SomeClass {
let fVariable = SomeClass()
fVariable.value = 10
return fVariable
}
The first one initializes variable to a newly created SomeClass instance, once at most (and maybe not even that many times). The second one is a read-only computed variable and creates a new SomeClass instance every time its value is read.

Your intuition is right, that article is incorrect. I'm guessing the author is conflating/confusing computed property syntax with the immediately-executed-closure trick. The lazy keyword has nothing to do with how many times the closure is executed. lazy simply causes the property to remain uninitialized until first access, at which point the expression on the right hand side of the equal sign is evaluated.
To simplify, this:
var myVar: MyType {
return MyType()
}
is very different than this:
var myVar: MyType = MyType()
which is similar in storage but has different initialization semantics than this:
lazy var myVar: MyType = MyType()
In the first example, myVar is a computed property and the code inside of the curly braces is executed every time myVar is accessed. In other words, every time you access myVar you'd get a newly created object back.
In the second example, myVar is a stored property and the expression after the equal sign is evaluated once during initialization of the class or struct that contains that property.
In the third example, myVar is still a stored property but the evaluation of the expression after the equal sign (be it an initializer expression, a function invocation, or a closure invocation) is delayed until it's accessed.
As a side note, this line of code:
lazy var myVar: MyType = { ... }()
is equivalent to:
func doStuffAndReturnMyType() { ... }
lazy var myVar: MyType = doStuffAndReturnMyType()
The shorthand in the first example wasn't specifically designed for–it just works because Swift's type system (is awesome and) treats closures as unnamed (anonymous) functions.

Related

Swift protocol with lazy property - Cannot use mutating getter on immutable value: '$0' is immutable

Goal: Create a protocol that allows lazy computation of a property for structs that conform to the protocol and then add the properties for an array of those structs. The computation is intensive and should only be executed once, hence the lazy requirement.
So, after lots of reading (eg this: Swift Struct with Lazy, private property conforming to Protocol) and trial and error (please don't flag this as a duplicate, unless it actually addresses this exact case), I came up with something that works:
import Foundation
protocol Foo {
var footype: Double { mutating get }
func calculateFoo() -> Double
}
struct Bar: Foo {
private lazy var _footype: Double = {
let value = calculateFoo()
return value
}()
var footype: Double {
mutating get {
return _footype
}
}
func calculateFoo() -> Double {
print("calc")
return 3.453
}
}
Testing this in a Playground:
var bar = Bar()
print(bar.footype)
print(bar.footype)
And the output is:
calc
3.453
3.453
So far, so good.
Now, I want to make an array of Bar and add the footype properties:
var bar1 = Bar()
var bar2 = Bar()
var bar3 = Bar()
var bars = [bar1, bar2, bar3]
print(bars.map { $0.footype }.reduce(0.0, +))
Which gives me the following error:
Cannot use mutating getter on immutable value: '$0' is immutable
Found a lot of info on this error, but am stuck how to solve it. One way would be to use class instead of struct, but that doesn't work well with other parts of the code.
Is it possible what I am trying to achieve?
As you can tell from the error message, $0 is immutable, so you can't use a mutating member on it.
Therefore, you can't iterate over the bars directly. What you can do is iterating through its indices, because we know that bars[$0] is mutable:
print(bars.indices.map { bars[$0].footype }.reduce(0.0, +))

Whether to use var or let during instances creation in Swift?

What should be used to create the instances of classes in Swift and why?
please explain the usage of let and var during the instances creation in Swift
below is the code :-
class ConstantTest{
let constant: String
init(constant: String) {
self.constant = constant
}
func printConstant() {
print(constant)
}
}
let constanttest = ConstantTest(constant: "Hello")
constanttest.printConstant()
var test = ConstantTest(constant: "Hie")
test.printConstant()
Use let if:
it is a constant (or in the case of reference types like class, if the reference cannot be replaced with another reference); and
you're able to set it during the initialization process.
But if you need to be able to change it at a later point, use var, such as true variables whose values are not constant (or in the case of reference types, if you need to replace it with another instance). But variables and properties whose values are not set during the initialization process, you have to use var. For example, lazy stored properties use var because their value is not set when the initialization process completes, but only when you first reference it. Another example includes view controllers' references to their outlets that are hooked up only when the view hierarchy is created at a later point.
Needless to say, computed properties use var, too.
But, if you can use let, you should do so, as it's easier to write safe code if you know what is a constant and what is a variable. In your example, you'd use let.
Note: In the case of reference types, like class types, let does not mean that that the object itself is necessarily immutable, merely that you cannot replace it with another instance. If you want to enjoy control over whether it's immutable or not, consider using a value type (e.g. a struct).
Let me see if I can make that final note more clear. Consider:
class Foo {
var value: String
init(value: String) {
self.value = value
}
}
Then the following is permitted:
let obj = Foo(value: "a")
obj.value = "b" // changing mutable property of reference type, Foo, is permitted
But the following is not:
let obj = Foo(value: "a")
obj = Foo(value: "b") // replacing `obj` with a new instance of `Foo`, is not
If you don't want to be able to change value property, you can define value to be immutable (or at least, not publicly mutable), e.g.:
class Foo {
let value: String // or `private(set) var value: String`
init(value: String) {
self.value = value
}
}
Or don't define Foo as class (a reference type) and instead define it to be a struct (a value type):
struct Foo {
var value: String
init(value: String) {
self.value = value
}
}
let obj = Foo(value: "a")
obj.value = "b" // this is not permitted, because Foo value-type, `obj`, was declared with `let`, making it immutable
Note, that final example, declaring Foo as a value type (a struct) does change it fairly fundamentally, e.g.
var obj1 = Foo(value: "a")
var obj2 = obj1 // this value is a copy of `obj1` not a reference to the same object that `obj1` pointed to
obj1.value = "b"
print("\(obj1.value)") // will print "b"
print("\(obj2.value)") // will print "a"
But value types, while it requires a slightly different mindset to use them, are incredibly useful for easily writing safe code. See WWDC 2015 Building Better Apps with Value Types in Swift.
There are varying reasons to use each. The simplest way to explain this is that let is for defining constants, while var is for defining variables. When using let the value cannot be changed. So in your application if you need a value that can be changed, use var. As well you might think of searching for your answer, as there are many duplicates of this question.
Source: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

Role of Swift 3 lazy var with no getter

I am wondering the meaning of lazy keyword when I am not working with a getter or setter. Look at this code:
class ViewController: UIViewController
{
lazy var toto = 5
}
The compiler accepts the lazy keyword but I do not know why. Lazy means the value will me calculated only when reading. But there is no need to compute anything for an integer value.
lazy means that the initial value of stored property is evaluated and assigned on the first access (so this is actually unrelated to getters
or setters which are used with computed properties).
lazy var toto = ... some expression evaluating to an `Int` ...
defines a lazy Int property.
lazy can be used to delay the evaluation of the initial value
until the property is needed, e.g. if that evaluation is
"expensive" or has side effects.
But from the language/compiler point of view, the initial value on the right-hand side
can be an arbitrary expression.
It does not matter if it is a constant or a "complicated" expression involving function calls.
lazy var a = 5 // A constant
lazy var b = someFunctionReturningAnInt() // Function call
lazy var c = { _ -> Int in
return 42
}() // Immediately evaluated closure
are all valid definitions. There is no advantage of using lazy with a constant initial value, but it is valid Swift.
You should only use lazy to initialize a new class variable.
The official Swift guide gives a very good example, summary as below:
class DataImporter {
init() {
//importing data, non-trivial task
}
}
class DataManager {
lazy var dataImporter = DataImporter()
init() {
//here, dataImporter is not yet created because it is lazy to move its ass~
}
let manager = DataManager() // manager.dataImporter is NOT created yet
manager.dataImporter //ONLY now it is created

Static calculation on demand?

I'm developing a class with a lot of functionality. Some functions need a lot of time, so I would store the result at creation for later access. But if this value is never needed, the calculation was wasted time.
In this case I would use a marker, if the value is already calculated. If yes, use the stored value. If not, it will calculate the value and store it in its static variable.
So I need the function itself, a marker and a variable for the saved result. Three items for every function!
Is there in Swift anything build in like "optional static functions"??
I would prefer to use
a = function()
for every call. The first call will calculate and save the result, all others will only take the precalculated result (like from a cache).
Lazy stored properties
In your comment below you describe that
But I don't meant global statically values, but for each instance. So
if you use foo1 and foo2, than foo2 needs to calculate its own
function for its own, because it only depends on values of foo2. It
can not rely on the globally calculated version which was done before
by foo1. So it is something like a "local static variable"
So it seems you may have a heavy computation for each instance of Foo, and you want to make certain that this computation is performed at most once, for each given instance of Foo. This demand is very close to the very definition of lazy (stored) properties in Swift: if a first call is made to get the value of a given lazy property, the property will be instantiated (e.g. by a call to some method, execution of a once-only executed closure, or simply by a given value/literal), and the value stored in the property. All subsequent calls to the lazy property will simply make use of the stored value (given you don't choose to mutate the property: lazy instance properties may not be immutables).
E.g., in practice:
class Foo {
lazy var bar: Int = self.reallyHeavyCalculation()
lazy var baz: Int = {
print("... heavy stuff")
return 2 * self.baq
}()
private func reallyHeavyCalculation() -> Int {
// ...
print("... other heavy stuff")
return 42
}
var bax: Int?
var baq: Int // instance value used in once-only computation
// of (lazy) property baz: at baz instantiation
init(baq: Int) { self.baq = baq }
}
let foo1 = Foo(baq: 50)
print("My first foo has never accessed his bar or baz")
foo1.bax = foo1.bar // at first call: compute 'bar' for this Foo instance
var baxBaz = foo1.bar // 'foo1.bar' already computed
print(foo1.baz) // at first call: compute 'baz' for this Foo instance
baxBaz = foo1.baz // 'foo1.baz' already computed
/* Prints:
My first foo has never accessed his bar or baz
... other heavy stuff
... heavy stuff
100 */
Static properties are always computed lazily
(When I initially read your question, I perceived your use case to be that of class/static properties, that are to be computed only once. I will leave this part of the answer as it is still relevant to the subject, and might be helpful to future readers)
Static properties are always computed lazily, meaning they will only be instantiated with a value given at least one call to them. After this instantiation, e.g. in case of a static immutable property, the once-only calculated value is readily available and stored in the static property.
We may read from the Language Guide - Properties:
Type Properties
...
Stored type properties are lazily initialized on their first access.
They are guaranteed to be initialized only once, even when accessed by
multiple threads simultaneously, and they do not need to be marked
with the lazy modifier.
...
Global and Local Variables
...
Global constants and variables are always computed lazily, in a
similar manner to Lazy Stored Properties. Unlike lazy stored
properties, global constants and variables do not need to be marked
with the lazy modifier.
We can verify this behavior with simple example:
class Foo {
static let foo: Int = reallyHeavyCalculation() // lazy
static let bar: Int = {
print("... heavy stuff")
return 99
}() // lazy
private static func reallyHeavyCalculation() -> Int {
// ...
print("... other heavy stuff")
return 42
}
var bax: Int? = nil
var baz = Foo.bar
}
print("I've never had a foo")
let foo1 = Foo()
// first initializion of instance member 'baz' by
// type member 'bar': compute bar
print("I have a foo")
foo1.bax = Foo.foo // at first call: compute 'Foo.foo'
let foo2 = Foo() // 'Foo.bar' already computed
print("I have another foo")
foo2.bax = Foo.foo // 'Foo'foo' already computed
/* Prints:
I've never had a foo
... heavy stuff
I have a foo
... other heavy stuff
I have another foo */
In the example above, the reallyHeavyComputation() (/closure associated with Foo.bar) method will be called exactly once in case you ask (at least once) for the value of the static immutable property Foo.foo (/Foo.bar). No additional calls will be made to reallyHeavyComputation() (/closure), even if you ask for the Foo.foo (/Foo.bar) value repeatedly.

How to create Non-optional stored properties for UIViewController Custom Subclass

When subclassing UIViewController ( and other similar classes ) we do not have to deal with any initialization, so if I create a stored property that is not an optional, Xcode will complain that there are no initializer.
So how can I create a non-optional store property in these classes? or should I?
You have 2 options:
initialize it inline
var myProp = MyClass()
declare it as implicitly unwrapped optional:
var myProp: MyClass!
and initialize it anywhere in the view controller - usually in viewDidLoad. This is the pattern commonly used for outlets, and one of the few cases where I tolerate implicitly unwrapped
Define the property with lazy.
lazy var myFoo : Foo = Foo()
or, if you need to do some stuff to setup myFoo:
lazy var myFoo : Foo = {
// Code to create myFoo
let foo = Foo(...)
// modify foo if you need to
return foo
}() // <== this is a function call; returns the configured `myFoo`
As a lazy var, myFoo will get assigned to its initial value when it is used for the first time.