I am confused about where to use lazy functionality, I mean to say in which type of condition I should use lazy keyword in the collection.

- 5,079
- 4
- 26
- 56

- 3,323
- 1
- 13
- 20
-
The accepted answer has nothing to do with `NSMutableDictionary.lazy` ... the `lazy` keyword for properties is completely different. – Alexander Mar 03 '17 at 15:28
3 Answers
Lazy evaluation is when the evaluation of an expression is deferred until the result is needed. This is in contrast to eager evaluation, which is when the evaluation of an expression is done immediately.
Consider this expression:
let input = [1, 2, 3]
let evens = input.map{ $0 * 2 }
Each number of numbers (1, 2, 3) is mapped to a new value by the closure { $0 * 2 }
, which multiplies them by 2. This evaluation is done eagerly. That is, the moment this line is being executed is when the evaluation of the map
function is performed, and the result of the computation is stored in evens
. The input
is of type Array<Int>
, and the result, evens
is also of type Array<Int>
.
Now consider this expression:
let input = [1, 2, 3]
let evens = input.lazy.map{ $0 * 2 }
Each number of numbers (1, 2, 3) will be to a new value by the closure { $0 * 2 }
, which multiplies them by 2. However, this evaluation is done lazily. That is, at the moment this line is being executed, the multiplication isn't done. Instead, the closure { $0 * 2 }
is stored for future reference. The input
is of type Array<Int>
, and the result, evens
is also of type LazyMapRandomAccessCollection<Array<Int>, Int>
. The multiplication is deferred until an element is accessed. If an element is never accessed, then it's never processed.
In such a trivial case, the bookkeeping overhead of storing the closure for future evaluation would be larger than just computing the results eagerly. However, you can envision a situation like this:
let input = 1...1000000000
let evens = input.lazy.map{ $0 * 2 }
print(evens[0])
Of all of the 1000000000
in the sequence, only one is ever used. Evaluating the closure 1000000000
times, to produce 1000000000
results, storing them all in memory is really inefficient, if only the first of the elements will ever be needed.
lazy
is an instance method of the Sequence
protocol. All conforming types, including NSMutableDictionary
implement it. They all do the same thing: they defer processing of elements in map
and filter
statements until the time that their results are needed. This can save memory and processing time in cases where there are many elements, and only a small portion of them are ever needed.

- 59,041
- 12
- 98
- 151
From Apple Docs:
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration.
When use @lazy
property then remembers below things:
- Lazy property must always declare with the
var
keyword, not with thelet
constant. - Lazy properties must be initialized when it is declared.
How we achieve lazy functionality in Objective-C
@property (nonatomic, strong) NSMutableArray *players;
- (NSMutableArray *)players
{
if (!_players) {
_players = [[NSMutableArray alloc] init];
}
return _players;
}
And now in Swift, you can achieve the same functionality by using lazy
property. See below example
class Person {
var name: String
lazy var personalizedGreeting: String = {
return "Hello, \(self.name)!"
}()
init(name: String) {
self.name = name
}
}
Now when you initialize a person, their personal greeting hasn’t been created yet:
let person = Person(name: "John Doe") // person.personalizedGreeting is nil
But when you attempt to print out the personalized greeting, it’s calculated on-the-fly:
print(person.personalizedGreeting)
// personalizedGreeting is calculated when used
// and now contains the value "Hello, John Doe!"
I hope this will help you to understand the functionality of lazy property.

- 1,680
- 12
- 21
The way lazy works is that the initializer (or init method) runs only when the variable or property is first accessed. I see one main reason why it won't work (at least straight away) in your code, and that is because you packed two lazy instantiation code into one method (loadEntriesIfNeeded).
To use lazy instantiation, you might need to extend NSMutableArray and NSDictionary and override or create a custom initializer for your lazy instantiation. Then, distribute the code inside loadEntriesIfNeeded into their respective initializers.
import Swift
println("begin")
class ClassWithLazyProperties {
lazy var entries:[String] = ClassWithLazyProperties.loadStuff()
lazy var entriesByNumber:Dictionary<Int, String> = {
var d = Dictionary<Int, String>()
for i in 0..<self.entries.count {
d[i] = self.entries[i]
}
return d
}()
private class func loadStuff() -> [String] {
return ["Acai", "Apples", "Apricots", "Avocado", "Ackee", "Bananas", "Bilberries"]
}
}
let c = ClassWithLazyProperties()
c.entriesByNumber
// 0: "Acai", 1: "Apples", 2: "Apricots", 3: "Avocado", 4: "Ackee", 5: "Bananas", 6: "Bilberries"]
println("end")

- 2,299
- 1
- 22
- 27
-
the question has nothing to do with `lazy var`s. Also, you should avoid writing things like `for i in 0..
– Alexander Mar 01 '17 at 05:41