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.