0
1
00:00:00,330 --> 00:00:06,360
Hey, it's me again, Angela from the App Brewery. Welcome to another Swift Deep Dive.
1

2
00:00:06,360 --> 00:00:12,660
And in this Deep Dive, we're going to talk about immutability, more specifically, what does it mean when
2

3
00:00:12,660 --> 00:00:16,750
we say that a struct is immutable?
3

4
00:00:16,990 --> 00:00:22,620
Let's quickly recap some key concepts. When we create a struct in our code,
4

5
00:00:22,780 --> 00:00:30,720
we're essentially creating a blueprint for an eventual object that will get created from our blueprint.
5

6
00:00:30,790 --> 00:00:37,000
And in this blueprint, we get to plan ahead for how this eventual object will be.
6

7
00:00:37,000 --> 00:00:45,100
For example, we create variables, such as our questionNumber. And when our variables live inside a struct,
7

8
00:00:45,520 --> 00:00:52,990
that variable is associated with our struct and it's known as a property of that struct.
8

9
00:00:52,990 --> 00:01:00,260
Similarly, we've created functions inside our struct. And when functions are created inside a struct, they're
9

10
00:01:00,260 --> 00:01:03,050
known as a method.
10

11
00:01:03,250 --> 00:01:10,600
So you can consider these properties as a way of defining what this eventual object created from the
11

12
00:01:10,600 --> 00:01:12,260
struct will be like,
12

13
00:01:12,310 --> 00:01:21,770
so its attributes or its properties. And the methods can be thought of as what the objects can do.
13

14
00:01:21,790 --> 00:01:29,380
So when we created our QuizBrain struct, we were essentially creating the blueprint for the eventual
14

15
00:01:29,380 --> 00:01:38,650
Quiz Brain that would get created, and we can take our blueprint and initialize it which turns it into
15

16
00:01:38,710 --> 00:01:41,140
the actual object.
16

17
00:01:41,140 --> 00:01:47,860
Now, we come on to the topic of Immutability. Swift is designed so that anything marked by the "let" keyword
17

18
00:01:48,040 --> 00:01:49,360
is immutable.
18

19
00:01:49,360 --> 00:01:51,690
But what does that mean?
19

20
00:01:51,700 --> 00:01:58,270
Suppose you created this structure from a bunch of different Lego blocks using the "let" keyword, but
20

21
00:01:58,480 --> 00:02:03,670
at some point, you decide that you want to change some aspect of it, say, the color of one of the bricks.
21

22
00:02:04,340 --> 00:02:10,870
Well, unfortunately, because the structure was created using the "let" keyword, meaning it's immutable,
22

23
00:02:10,870 --> 00:02:14,690
you can't just change this one brick from green to yellow.
23

24
00:02:15,020 --> 00:02:21,610
Well, instead, you have to destroy the entire structure and create a brand-new one that has a yellow brick
24

25
00:02:21,610 --> 00:02:23,530
there instead.
25

26
00:02:23,530 --> 00:02:29,790
So the way that I think about immutability is, imagine if you created a sculpture from stone, right,
26

27
00:02:29,830 --> 00:02:35,760
if you created Michelangelo's David and you decided that it should have a larger nose,
27

28
00:02:35,770 --> 00:02:40,940
well, you can't just come along and chip away at the stone because the nose is already too small,
28

29
00:02:40,960 --> 00:02:48,760
what you actually have to do is to completely destroy the sculpture and carve a new one with this gigantic
29

30
00:02:48,850 --> 00:02:53,690
ugly looking nose. and that's how you would work with immutable objects.
30

31
00:02:53,740 --> 00:02:58,830
You destroy the old copy and create a new copy that encompasses the change.
31

32
00:02:58,870 --> 00:03:03,550
So how does this discussion about immutability relate back to our Swift code?
32

33
00:03:04,240 --> 00:03:10,780
Well, firstly, it relates to the keywords "var" and "let." Things marked with "var" are mutable and things marked
33

34
00:03:10,780 --> 00:03:18,940
with "let" are immutable. But immutability also relates to struct. With struct, Swift makes an additional
34

35
00:03:18,940 --> 00:03:19,690
distinction.
35

36
00:03:20,170 --> 00:03:27,370
There's a difference between mutating a struct from the outside and changing a property from inside
36

37
00:03:27,370 --> 00:03:28,920
the struct.
37

38
00:03:28,990 --> 00:03:33,210
Let's go back to the example of my town, so I can show you what I mean.
38

39
00:03:33,310 --> 00:03:37,420
Remember when my other hero Keanu Reeves moved into my town,
39

40
00:03:37,420 --> 00:03:43,750
well, I certainly remember. In this case, we changed the citizen's property from outside the struct.
40

41
00:03:43,750 --> 00:03:49,090
We wrote myTown.citizens.append and mutated the citizen's property.
41

42
00:03:49,360 --> 00:03:54,310
But now let me show you what happens when we try to change a property of our structure from within the
42

43
00:03:54,310 --> 00:03:56,150
structure itself.
43

44
00:03:56,170 --> 00:04:03,670
So suppose that we wanted to create a function inside our town struct that allows us to change the resources.
44

45
00:04:03,670 --> 00:04:12,130
Suppose that in our town, we also had a method called harvest rice, and in this case, what happens is we
45

46
00:04:12,130 --> 00:04:15,290
add some rice to our resources, right?
46

47
00:04:15,310 --> 00:04:21,970
So this is a property of our town which is a dictionary that has a string as a key and an integer as
47

48
00:04:21,970 --> 00:04:25,060
the value of the amount of resources we have.
48

49
00:04:25,060 --> 00:04:31,410
So when we harvest rice, what actually happens behind the scenes is we tap into our resources,
49

50
00:04:31,540 --> 00:04:38,330
we go ahead and reach in and look for the rice resource, and then we set it to equal 100 bags.
50

51
00:04:38,560 --> 00:04:44,410
But in this case, we have a method that changes a property of our struct from within the struct. And we
51

52
00:04:44,410 --> 00:04:49,330
get an error "Cannot assign through subscript: 'self' is immutable."
52

53
00:04:49,330 --> 00:04:51,620
What does that mean exactly?
53

54
00:04:51,700 --> 00:04:53,290
What's actually going on here?
54

55
00:04:54,100 --> 00:04:59,320
Well, we're trying to mutate the resources property of the struct itself.
55

56
00:04:59,620 --> 00:05:09,240
The code that we wrote is actually shorthand for self.resources, brackets "Rice" equals 100.
56

57
00:05:09,250 --> 00:05:13,930
That's why the error message mentions "self is immutable."
57

58
00:05:13,930 --> 00:05:18,210
You can think of "self" as a property gets automatically created.
58

59
00:05:18,660 --> 00:05:25,490
We can always access "self" inside a method, just like how we did in our "init" function with
59

60
00:05:25,510 --> 00:05:28,670
self.citizens or self.resources.
60

61
00:05:28,830 --> 00:05:36,570
And it refers to an instance of the structure itself from within the structure's declaration.
61

62
00:05:36,660 --> 00:05:37,800
But here's the catch, though.
62

63
00:05:38,280 --> 00:05:46,560
Inside a struct, when "self" is created automatically in the background, it's defined with the "let" keyword.
63

64
00:05:46,560 --> 00:05:48,680
That's why "self is immutable."
64

65
00:05:48,750 --> 00:05:55,980
So if we want to mutate any property from within our structure like self.resources, then we need
65

66
00:05:55,980 --> 00:06:03,180
to mark our harvestRice method with a special keyword called mutating, and then you'll see all our errors
66

67
00:06:03,240 --> 00:06:04,710
will go away.
67

68
00:06:04,710 --> 00:06:14,700
So now we can say myTown.harvestRice, and then we can go ahead and print myTown.resources,
68

69
00:06:15,120 --> 00:06:21,600
and you can see that when this code runs, that in addition to having some wool, to begin with, we've also
69

70
00:06:21,600 --> 00:06:29,130
got a bunch of rice now. Yay, foods! And the only thing we had to do is that if we're making a method that
70

71
00:06:29,130 --> 00:06:36,450
modifies one of the properties from within the struct, then we have to mark that method as mutating.
71

72
00:06:36,450 --> 00:06:43,740
By marking the method as mutating, "self" will behave like a "var" and we can freely change any of our struct
72

73
00:06:43,800 --> 00:06:49,880
properties. And the other way to look at this is by thinking of struct as having two kinds of methods.
73

74
00:06:49,980 --> 00:06:56,070
The first kind of a method is a plain method that doesn't change anything about the struct. But the second
74

75
00:06:56,070 --> 00:07:02,070
kind of method is a mutating method that can change the state of the structure.
75

76
00:07:02,070 --> 00:07:05,630
So given everything we've talked about, I've got a question for you.
76

77
00:07:05,760 --> 00:07:13,950
Do you think you can call harvest rice if we wrote "let myTown instead?
77

78
00:07:14,120 --> 00:07:15,660
Well, the answer is No.
78

79
00:07:15,700 --> 00:07:22,400
When we use the "let" keyword, our struct and all its properties are immutable and we cannot call a mutating
79

80
00:07:22,400 --> 00:07:24,720
function like harvestRice.
80

81
00:07:24,950 --> 00:07:27,760
And that wraps up our Deep Dive on immutability.
81

82
00:07:27,770 --> 00:07:28,970
See you in the next lesson.
