1 00:00:06,630 --> 00:00:10,380 - In the previous lesson, we looked at ownership in Rust 2 00:00:10,380 --> 00:00:13,470 and we saw that for types that don't implement Copy, 3 00:00:13,470 --> 00:00:15,990 most types don't implement Copy. 4 00:00:15,990 --> 00:00:18,570 Then when you assign one variable to another 5 00:00:18,570 --> 00:00:21,330 you move ownership to the new variable 6 00:00:21,330 --> 00:00:24,150 and the old variable loses its value 7 00:00:24,150 --> 00:00:25,833 and you can't use it anymore. 8 00:00:26,850 --> 00:00:28,830 So if this is all we had in Rust, 9 00:00:28,830 --> 00:00:30,630 it would be quite restrictive. 10 00:00:30,630 --> 00:00:34,050 Whenever you assign one variable to another, 11 00:00:34,050 --> 00:00:36,180 you lose the original variable. 12 00:00:36,180 --> 00:00:39,000 How would you deal with that in a large program? 13 00:00:39,000 --> 00:00:40,650 Luckily for us, there's another mechanism 14 00:00:40,650 --> 00:00:41,970 which complements ownership, 15 00:00:41,970 --> 00:00:43,270 and it's called borrowing. 16 00:00:44,430 --> 00:00:46,500 Basically it uses references. 17 00:00:46,500 --> 00:00:49,100 You can either think of it as a reference or pointer 18 00:00:50,400 --> 00:00:53,760 whichever you kind of feel easiest to understand. 19 00:00:53,760 --> 00:00:56,280 But basically you can reference an object 20 00:00:56,280 --> 00:00:57,720 without claiming ownership. 21 00:00:57,720 --> 00:00:59,370 It's called borrowing. 22 00:00:59,370 --> 00:01:01,950 Okay? So in Rust, when it talks about borrowing 23 00:01:01,950 --> 00:01:03,960 it means you've got a reference to an object 24 00:01:03,960 --> 00:01:05,610 but you don't own it. 25 00:01:05,610 --> 00:01:07,623 The original variable still owns it. 26 00:01:08,910 --> 00:01:11,610 Okay? So that's what this lesson's all about. 27 00:01:11,610 --> 00:01:14,010 So the syntax for borrowing a value 28 00:01:14,010 --> 00:01:15,630 it uses an ampersand. 29 00:01:15,630 --> 00:01:17,910 I would say at this point, if you are coming 30 00:01:17,910 --> 00:01:22,050 from a background in C or C++, don't try too hard 31 00:01:22,050 --> 00:01:24,840 to compare the syntax because you'll go nuts. 32 00:01:24,840 --> 00:01:26,340 The syntax is different in Rust 33 00:01:26,340 --> 00:01:28,530 and you just have to go with it. 34 00:01:28,530 --> 00:01:31,110 So you put an ampersand before a variable, 35 00:01:31,110 --> 00:01:34,710 in C++ that would mean take the address, 36 00:01:34,710 --> 00:01:38,640 in Rust it means borrow or take a reference. 37 00:01:38,640 --> 00:01:40,230 Let's have a look at this example. 38 00:01:40,230 --> 00:01:43,620 I've got a string object, s, let me draw it here. 39 00:01:43,620 --> 00:01:45,480 S is my string object 40 00:01:45,480 --> 00:01:49,200 and it has a pointer to a buffer on the heap. 41 00:01:49,200 --> 00:01:53,730 Huey one of Donald Duck's nephews, I do believe. 42 00:01:53,730 --> 00:01:57,120 And then I declare a reference variable, r, 43 00:01:57,120 --> 00:01:58,890 borrows the value of s. 44 00:01:58,890 --> 00:02:01,410 Okay? I haven't typed r explicitly here. 45 00:02:01,410 --> 00:02:04,140 I'll show you that syntax shortly. 46 00:02:04,140 --> 00:02:06,720 But when you put an ampersand in front of a variable 47 00:02:06,720 --> 00:02:10,200 it doesn't take the address of, it borrows. 48 00:02:10,200 --> 00:02:15,200 So what we end up with is r, is effectively a reference 49 00:02:15,360 --> 00:02:18,570 to the original variable s, okay? 50 00:02:18,570 --> 00:02:20,760 And effectively an alias for it. 51 00:02:20,760 --> 00:02:23,700 So in your application, when you print out s, 52 00:02:23,700 --> 00:02:24,750 it'll print out huey, 53 00:02:25,991 --> 00:02:28,320 and when you print out r, r is a reference 54 00:02:28,320 --> 00:02:31,170 to that string object, and it prints out huey. 55 00:02:31,170 --> 00:02:33,780 Okay? So reference is kind of automatically 56 00:02:33,780 --> 00:02:36,690 dereferenced on usage to give you the string 57 00:02:36,690 --> 00:02:38,326 that you first thought of. 58 00:02:38,326 --> 00:02:41,790 The thing is that s is still the owner of that string 59 00:02:41,790 --> 00:02:44,133 and r is just kind of like an observer. 60 00:02:45,600 --> 00:02:48,060 Right, so r is a reference variable. 61 00:02:48,060 --> 00:02:51,783 R borrows the value of s, but still s is the owner. 62 00:02:53,370 --> 00:02:54,540 Okay. 63 00:02:54,540 --> 00:02:56,700 Right, if you want to use explicit typing 64 00:02:56,700 --> 00:02:58,680 rather than type inference, 65 00:02:58,680 --> 00:03:01,680 then when you declare a reference variable, 66 00:03:01,680 --> 00:03:03,420 again, you've gotta use an ampersand. 67 00:03:03,420 --> 00:03:05,250 So you use the ampersand twice 68 00:03:05,250 --> 00:03:07,770 once to borrow the value and once to declare 69 00:03:07,770 --> 00:03:10,410 the variable that's gonna hold the reference. 70 00:03:10,410 --> 00:03:11,970 So it looks like this. 71 00:03:11,970 --> 00:03:14,220 And another recommendation, if you're coming 72 00:03:14,220 --> 00:03:15,930 from a C++ background. 73 00:03:15,930 --> 00:03:20,930 In C++, so let me just do a momentary illusion here. 74 00:03:21,360 --> 00:03:24,870 So in C++, if you wanted to declare a reference variable 75 00:03:24,870 --> 00:03:27,660 you would declare it like that with an ampersand 76 00:03:27,660 --> 00:03:28,560 at the end of string. 77 00:03:28,560 --> 00:03:29,850 That would be a reference. 78 00:03:29,850 --> 00:03:31,440 Doesn't work like that in Rust. 79 00:03:31,440 --> 00:03:35,160 In Rust, the ampersand always comes before the value 80 00:03:35,160 --> 00:03:40,160 to borrow it and before the type to make it a reference. 81 00:03:40,320 --> 00:03:41,520 Let's look at this example then. 82 00:03:41,520 --> 00:03:46,520 First of all, I declare s, s is a string variable. 83 00:03:46,890 --> 00:03:50,130 It holds pointer to louie. 84 00:03:50,130 --> 00:03:53,220 Not sure if I spelled that right, but anyway 85 00:03:53,220 --> 00:03:55,860 you know it's duckling number two 86 00:03:55,860 --> 00:03:57,630 in the Donald Duck family, 87 00:03:57,630 --> 00:04:02,630 and r, it takes a reference to s, or it borrows s. 88 00:04:02,910 --> 00:04:04,050 You can say it either way. 89 00:04:04,050 --> 00:04:06,780 A Rust developer would say, I'm borrowing s. 90 00:04:06,780 --> 00:04:08,250 And if you get any error messages 91 00:04:08,250 --> 00:04:10,260 it'll always talk about borrowing. 92 00:04:10,260 --> 00:04:12,750 You can think of it as being, taking a reference to 93 00:04:12,750 --> 00:04:14,940 or you can think of it as being borrowing. 94 00:04:14,940 --> 00:04:19,200 R will borrow or reference if you like, 95 00:04:19,200 --> 00:04:24,200 s, technically r is a reference to a string. 96 00:04:24,330 --> 00:04:26,760 Okay? So the ampersand goes before the type, 97 00:04:26,760 --> 00:04:28,500 r is a reference to a string. 98 00:04:28,500 --> 00:04:31,770 In particular, it references this string, up here. 99 00:04:31,770 --> 00:04:34,020 So again, using explicit typing, 100 00:04:34,020 --> 00:04:35,580 the result's gonna be the same here, isn't it? 101 00:04:35,580 --> 00:04:38,340 When I output s, it'll be louie. 102 00:04:38,340 --> 00:04:41,610 When I output r, it'll be referring to that string 103 00:04:41,610 --> 00:04:44,040 and it'll be louie again. 104 00:04:44,040 --> 00:04:46,980 Okay? So explicit typing is useful. 105 00:04:46,980 --> 00:04:49,410 When you've got functions, it enables you to say 106 00:04:49,410 --> 00:04:51,480 this function takes a reference 107 00:04:51,480 --> 00:04:54,600 to a string or returns a reference to a string. 108 00:04:54,600 --> 00:04:56,100 Borrowing would be the terminology. 109 00:04:56,100 --> 00:04:58,440 You can say a function borrows the value 110 00:04:58,440 --> 00:04:59,610 but it doesn't own it. 111 00:04:59,610 --> 00:05:03,573 R borrows the value of s, but s is still the owner. 112 00:05:04,500 --> 00:05:06,810 Right, you can have mutable borrowing. 113 00:05:06,810 --> 00:05:09,270 If your original object is mutable 114 00:05:09,270 --> 00:05:13,050 then you can have declared via the mutable keyword or mut. 115 00:05:13,050 --> 00:05:15,870 Then you can also borrow the value mutably as well. 116 00:05:15,870 --> 00:05:20,250 You declare a mutable reference like that, okay? 117 00:05:20,250 --> 00:05:21,750 So that means that the reference 118 00:05:21,750 --> 00:05:24,000 is also allowed to change the value. 119 00:05:24,000 --> 00:05:26,880 You can change the value via the reference. 120 00:05:26,880 --> 00:05:28,590 Here's a simple example. 121 00:05:28,590 --> 00:05:31,740 We've completed the trilogy of ducklings here, dewey. 122 00:05:31,740 --> 00:05:36,540 So s, notice the s is a mutable string that's worth noting. 123 00:05:36,540 --> 00:05:38,160 Otherwise we couldn't change anything. 124 00:05:38,160 --> 00:05:39,900 You can't take a mutable reference 125 00:05:39,900 --> 00:05:43,890 unless the actual object itself is originally mutable. 126 00:05:43,890 --> 00:05:47,430 So s is a string object 127 00:05:47,430 --> 00:05:50,400 and it holds a pointer to this text. 128 00:05:50,400 --> 00:05:53,610 Dewey, very good. 129 00:05:53,610 --> 00:05:57,300 And then here you have to take a mutable reference of s. 130 00:05:57,300 --> 00:06:01,500 If I didn't put the mut keyword in here 131 00:06:01,500 --> 00:06:04,890 then I would just have a, my reference would be read only. 132 00:06:04,890 --> 00:06:06,540 Okay? The object might be changeable 133 00:06:06,540 --> 00:06:08,970 but my reference would be not mutable. 134 00:06:08,970 --> 00:06:10,280 So if you want to be able to change the value 135 00:06:10,280 --> 00:06:11,760 to the reference as well 136 00:06:11,760 --> 00:06:14,550 then you have to take a mutable reference. 137 00:06:14,550 --> 00:06:16,530 Okay? So you can change the underlying object. 138 00:06:16,530 --> 00:06:18,540 And if you want to use strong type then, 139 00:06:18,540 --> 00:06:22,770 then you'd have to say r is a mutable reference to a string. 140 00:06:22,770 --> 00:06:26,850 So r is a mutable reference to the string. 141 00:06:26,850 --> 00:06:29,700 So I can change the value via the string. 142 00:06:29,700 --> 00:06:32,610 I can also change the value via the reference 143 00:06:32,610 --> 00:06:37,050 because the reference is also declared as a mutable thing. 144 00:06:37,050 --> 00:06:40,530 So via the reference, I can do a push string. 145 00:06:40,530 --> 00:06:45,360 So, dewey, duck, okay, like that. 146 00:06:45,360 --> 00:06:49,590 So via the reference, r refers to this string object. 147 00:06:49,590 --> 00:06:50,670 So basically it's that string 148 00:06:50,670 --> 00:06:53,220 as we have an alias for, it'll append duck 149 00:06:53,220 --> 00:06:56,250 on the end, when it prints out the r string here 150 00:06:56,250 --> 00:06:57,963 it'll print out dewey duck. 151 00:06:59,280 --> 00:07:02,700 Right, example time for this lesson. 152 00:07:02,700 --> 00:07:05,400 The project is lesson07_borrowing. 153 00:07:05,400 --> 00:07:09,023 If you open that up in the Rust folder, and let's do that. 154 00:07:09,023 --> 00:07:12,030 And the code we're going to run, demo_simple_borrowing. 155 00:07:12,030 --> 00:07:14,490 We'll run it as usual using cargo run. 156 00:07:14,490 --> 00:07:16,830 Let's take a look at that code now. 157 00:07:16,830 --> 00:07:21,090 Okay, so I've opened lesson07_borrowing in VS Code 158 00:07:21,090 --> 00:07:23,850 and same kind of structure as before. 159 00:07:23,850 --> 00:07:28,850 In my main function, I declare various modules 160 00:07:29,040 --> 00:07:32,550 one per section in the lesson 161 00:07:32,550 --> 00:07:36,510 and then I call the appropriate entry point function. 162 00:07:36,510 --> 00:07:39,420 In my demo_simple_borrowing module 163 00:07:39,420 --> 00:07:40,803 called the do_it function. 164 00:07:41,640 --> 00:07:44,403 Okay, so demo_simple_borrowing. 165 00:07:45,360 --> 00:07:47,700 Here's my do_it function. 166 00:07:47,700 --> 00:07:51,210 It shows implicit borrowing 167 00:07:51,210 --> 00:07:54,840 explicitly typed borrowing, and mutable borrowing. 168 00:07:54,840 --> 00:07:57,540 Okay? So these are the three functions down here 169 00:07:57,540 --> 00:07:58,890 that we're going to look at. 170 00:07:58,890 --> 00:08:02,880 We'll run it and then we'll dissect the output 171 00:08:02,880 --> 00:08:04,950 when we look at the code. 172 00:08:04,950 --> 00:08:05,973 Cargo run. 173 00:08:08,130 --> 00:08:11,340 Okay? In demo_simple_borrowing, do_it. 174 00:08:11,340 --> 00:08:13,320 Yes, indeed. 175 00:08:13,320 --> 00:08:15,690 So for the implicitly typed borrowing function 176 00:08:15,690 --> 00:08:17,430 let's have a look at that. 177 00:08:17,430 --> 00:08:21,723 So s1 is a string, huey, r1 is a reference to it. 178 00:08:23,190 --> 00:08:25,656 So I can output s1 or r1. 179 00:08:25,656 --> 00:08:27,210 R1 is effectively just an alias. 180 00:08:27,210 --> 00:08:29,730 So in both cases, s1 and r1 181 00:08:29,730 --> 00:08:32,073 it's the same underlying text obviously. 182 00:08:32,940 --> 00:08:35,580 So that was using implicit typing, which is probably 183 00:08:35,580 --> 00:08:37,320 what you would actually do in practice. 184 00:08:37,320 --> 00:08:40,710 If you want to gain some brownie points, if you just 185 00:08:40,710 --> 00:08:43,800 wanna check your knowledge, you can use explicit typing. 186 00:08:43,800 --> 00:08:48,800 S2 is a string, and r2 is a reference to a string, 187 00:08:49,770 --> 00:08:53,220 in particular, it borrows or refers to s2. 188 00:08:53,220 --> 00:08:58,220 So s2 and r2, r2 is effectively an alias for s2. 189 00:08:58,530 --> 00:09:01,470 So in both those cases it'll print out louie, 190 00:09:01,470 --> 00:09:05,430 in my explicitly typed part, louie and louie. 191 00:09:05,430 --> 00:09:07,800 And then finally, for mutable borrowing, 192 00:09:07,800 --> 00:09:11,160 here's my mutable string, dewey, 193 00:09:11,160 --> 00:09:14,550 take a mutable reference to borrow it mutably, 194 00:09:14,550 --> 00:09:17,793 and put it into a mutable string reference. 195 00:09:18,840 --> 00:09:20,610 Either using s3, 196 00:09:20,610 --> 00:09:23,850 or the thing that refers to it, we can change the value. 197 00:09:23,850 --> 00:09:28,850 So when we output it s, so r3 is dewey duck. 198 00:09:29,490 --> 00:09:30,843 Okay, fantastic. 199 00:09:31,920 --> 00:09:33,390 Right. One other thing, I suppose. 200 00:09:33,390 --> 00:09:35,910 When you declare a mutable reference 201 00:09:35,910 --> 00:09:38,040 if you take a mutable reference like this 202 00:09:38,040 --> 00:09:41,190 then truly the compiler would understand 203 00:09:41,190 --> 00:09:42,990 that r3 is a mutable reference 204 00:09:42,990 --> 00:09:45,570 without you having to actually say it explicitly. 205 00:09:45,570 --> 00:09:49,980 And also s3 is clearly a string, isn't it as well? 206 00:09:49,980 --> 00:09:52,320 So how about if we used inferred typing 207 00:09:52,320 --> 00:09:54,600 to say this is a mutable string 208 00:09:54,600 --> 00:09:57,690 and this is a mutable reference, okay. 209 00:09:57,690 --> 00:09:59,140 Do you think that would work? 210 00:10:01,470 --> 00:10:02,400 Oh, yes. 211 00:10:02,400 --> 00:10:03,810 And that would be the preferred syntax. 212 00:10:03,810 --> 00:10:06,180 You know, there's no particular merit 213 00:10:06,180 --> 00:10:08,490 in typing things explicitly 214 00:10:08,490 --> 00:10:10,860 if you can get by using type inference. 215 00:10:10,860 --> 00:10:12,810 So that would be my preferred approach.