1 00:00:06,434 --> 00:00:09,840 - In the previous section, we saw what happened. 2 00:00:09,840 --> 00:00:11,910 when you pass a non-copy structure, 3 00:00:11,910 --> 00:00:15,630 like employee by value into a function. 4 00:00:15,630 --> 00:00:19,710 The call function receives ownership of the object. 5 00:00:19,710 --> 00:00:22,140 The calling function loses ownership 6 00:00:22,140 --> 00:00:24,300 and can't use the object afterwards. 7 00:00:24,300 --> 00:00:25,173 So it's gone. 8 00:00:26,070 --> 00:00:27,810 That's quite dramatic. 9 00:00:27,810 --> 00:00:30,090 Generally, a better approach 10 00:00:30,090 --> 00:00:33,030 is to pass structures by reference instead. 11 00:00:33,030 --> 00:00:36,750 In that case, the called function borrows the structure, 12 00:00:36,750 --> 00:00:39,570 it becomes a reference, but it doesn't own it. 13 00:00:39,570 --> 00:00:41,970 The calling function retains ownership 14 00:00:41,970 --> 00:00:45,240 and can continue to use the structure afterwards. 15 00:00:45,240 --> 00:00:47,310 So you don't give the object away, 16 00:00:47,310 --> 00:00:49,590 you just let the function borrow the object 17 00:00:49,590 --> 00:00:53,220 but you retain ownership back in your calling function. 18 00:00:53,220 --> 00:00:55,980 That's a much better approach. 19 00:00:55,980 --> 00:00:58,620 So let's have a look at this example. 20 00:00:58,620 --> 00:01:01,354 This function, print_employee, 21 00:01:01,354 --> 00:01:06,210 it receives an immutable reference to an employee. 22 00:01:06,210 --> 00:01:07,650 So we just use the ampersand, 23 00:01:07,650 --> 00:01:09,510 kind of what you'd expect actually. 24 00:01:09,510 --> 00:01:13,860 So you can imagine that e is kinda like a reference 25 00:01:13,860 --> 00:01:17,760 to an Employee object that sits elsewhere 26 00:01:17,760 --> 00:01:20,670 and in that object, it has a name 27 00:01:20,670 --> 00:01:24,570 and a salary and a full-time status like so. 28 00:01:24,570 --> 00:01:27,030 So in order to access the fields in the structure, 29 00:01:27,030 --> 00:01:29,250 well, you can actually use two syntaxes. 30 00:01:29,250 --> 00:01:30,930 And this is really gonna confuse you 31 00:01:30,930 --> 00:01:32,670 if you're a C++ developer 32 00:01:32,670 --> 00:01:35,343 and I was confused by this as well. 33 00:01:36,270 --> 00:01:38,670 So references, it's kind 34 00:01:38,670 --> 00:01:41,700 of like a mixed thing really in Rust. 35 00:01:41,700 --> 00:01:43,530 It looks like a reference 36 00:01:43,530 --> 00:01:46,920 if you're a C++ developer, but really, to be honest, 37 00:01:46,920 --> 00:01:49,560 it behaves more like a pointer actually. 38 00:01:49,560 --> 00:01:51,600 So what you could do 39 00:01:51,600 --> 00:01:55,039 is you could dereference the pointer explicitly to go 40 00:01:55,039 --> 00:01:57,600 to the object that you're referring to. 41 00:01:57,600 --> 00:01:58,893 So go over here. 42 00:02:00,840 --> 00:02:04,020 So star e is effectively like the contents 43 00:02:04,020 --> 00:02:05,640 of the object you pointed to. 44 00:02:05,640 --> 00:02:06,960 And then once you've got there, 45 00:02:06,960 --> 00:02:09,273 you could access a field inside. 46 00:02:10,380 --> 00:02:13,923 So that would be one approach using an explicit reference. 47 00:02:15,060 --> 00:02:18,720 But confusingly, you can also use an implicit reference, 48 00:02:18,720 --> 00:02:20,273 an implicit dereference, like that. 49 00:02:21,790 --> 00:02:24,570 So you can either say star e, or you can just say e. 50 00:02:24,570 --> 00:02:27,210 Effectively, what the compiler does, 51 00:02:27,210 --> 00:02:29,370 when you use a reference, 52 00:02:29,370 --> 00:02:31,890 the compiler knows that e is a reference. 53 00:02:31,890 --> 00:02:35,190 It can quite clearly see that e is a reference. 54 00:02:35,190 --> 00:02:38,490 So it will automatically dereference itself 55 00:02:38,490 --> 00:02:41,340 as if you said star and give you the contents 56 00:02:41,340 --> 00:02:42,213 of the employee. 57 00:02:43,140 --> 00:02:47,340 So this code here, the compiler will effectively convert it 58 00:02:47,340 --> 00:02:50,040 into that code for you. 59 00:02:50,040 --> 00:02:51,780 You can write it either way. 60 00:02:51,780 --> 00:02:52,680 And guess what? 61 00:02:52,680 --> 00:02:55,500 Rust developers tend to write it this way 62 00:02:55,500 --> 00:02:56,973 because it's less noise. 63 00:02:58,170 --> 00:03:00,300 Well, that's the idea of passing 64 00:03:00,300 --> 00:03:02,610 or receiving a reference parameter. 65 00:03:02,610 --> 00:03:06,090 Let's go through the whole kind of workflow. 66 00:03:06,090 --> 00:03:08,490 So let's see what happens from the top. 67 00:03:08,490 --> 00:03:10,560 Here is my higher-level function 68 00:03:10,560 --> 00:03:13,020 and in here, I create an employee object. 69 00:03:13,020 --> 00:03:16,350 So e1 is here 70 00:03:16,350 --> 00:03:21,300 and it's got a name and a salary and a full-time status. 71 00:03:21,300 --> 00:03:25,020 When you wanna pass by reference, or to put it another way, 72 00:03:25,020 --> 00:03:28,080 a function that borrows the employee, 73 00:03:28,080 --> 00:03:31,950 you have to use the ampersand to pass it in by reference. 74 00:03:31,950 --> 00:03:36,950 So this receives a reference to the employee like so 75 00:03:39,180 --> 00:03:42,480 and then as we've seen in my function at the top, 76 00:03:42,480 --> 00:03:44,730 I can either dereference explicitly 77 00:03:44,730 --> 00:03:47,910 or I can dereference implicitly to basically go 78 00:03:47,910 --> 00:03:50,230 to the employee that we're referring to 79 00:03:51,300 --> 00:03:54,393 and to access the fields inside. 80 00:03:55,890 --> 00:03:58,890 So this example is an immutable reference. 81 00:03:58,890 --> 00:04:00,660 I think you can probably imagine what it would look like 82 00:04:00,660 --> 00:04:02,730 if you wanted to have a mutable reference. 83 00:04:02,730 --> 00:04:05,430 You just put the mut, mut keyword everywhere. 84 00:04:05,430 --> 00:04:09,270 So this function receives a mutable reference 85 00:04:09,270 --> 00:04:10,440 to an employee. 86 00:04:10,440 --> 00:04:13,350 Obviously, the employee itself would have to be mutable 87 00:04:13,350 --> 00:04:14,610 in the first place. 88 00:04:14,610 --> 00:04:17,010 And then we can, for example, 89 00:04:17,010 --> 00:04:19,840 give the person a pay rise, I can say dereference 90 00:04:21,660 --> 00:04:25,560 and go to the employee and increase the salary. 91 00:04:25,560 --> 00:04:28,230 That's an explicit dereference using a star, 92 00:04:28,230 --> 00:04:29,580 like contents of 93 00:04:29,580 --> 00:04:32,550 or you can just use an implicit dereference. 94 00:04:32,550 --> 00:04:35,550 And if you use the implicit dereference syntax here, 95 00:04:35,550 --> 00:04:37,530 then the compiler will effectively convert it 96 00:04:37,530 --> 00:04:39,210 into that anyway. 97 00:04:39,210 --> 00:04:42,420 So in reality, you know, people just use this syntax 98 00:04:42,420 --> 00:04:45,030 because it's just simpler to read. 99 00:04:45,030 --> 00:04:47,760 All right, so from the top then, 100 00:04:47,760 --> 00:04:49,710 let's say I've got my high-level function 101 00:04:49,710 --> 00:04:52,867 and in here, I create a mutable employee, e1. 102 00:04:54,665 --> 00:04:56,460 So that has mutable everything. 103 00:04:56,460 --> 00:04:58,050 When you declare a mutable object, 104 00:04:58,050 --> 00:05:01,800 everything inside it is mutable, all the fields are mutable, 105 00:05:01,800 --> 00:05:06,480 the name and the salary and the full-time status. 106 00:05:06,480 --> 00:05:08,790 I then pass a mutable reference. 107 00:05:08,790 --> 00:05:11,550 Remember, when you pass in mutable references, 108 00:05:11,550 --> 00:05:13,650 the ampersand means it's a reference, 109 00:05:13,650 --> 00:05:16,230 meaning you're borrowing, not owning 110 00:05:16,230 --> 00:05:18,132 and it's a mutable reference. 111 00:05:18,132 --> 00:05:21,150 So the mut keyword is needed there 112 00:05:21,150 --> 00:05:23,790 and it's needed here just to make sure 113 00:05:23,790 --> 00:05:25,050 that you are being consistent. 114 00:05:25,050 --> 00:05:29,190 So this function receives a mutable reference like so 115 00:05:29,190 --> 00:05:30,810 and it can change the fields 116 00:05:30,810 --> 00:05:33,720 either using explicit or implicit dereferencing 117 00:05:33,720 --> 00:05:36,183 to access the fields in the object. 118 00:05:37,350 --> 00:05:39,690 So that actually is quite intuitive I think 119 00:05:39,690 --> 00:05:41,490 once you've kind of got the idea. 120 00:05:41,490 --> 00:05:44,370 That seems to be consistent with what you might expect. 121 00:05:44,370 --> 00:05:47,160 So an example, usual project. 122 00:05:47,160 --> 00:05:51,120 The files involved for this part will be mytypes obviously, 123 00:05:51,120 --> 00:05:54,210 which defines the employee structure, the main code, 124 00:05:54,210 --> 00:05:57,030 which declares the module and gets things going. 125 00:05:57,030 --> 00:05:59,160 And the demo file for this part of the demo, 126 00:05:59,160 --> 00:06:02,430 demo _struct_pass by reference, 127 00:06:02,430 --> 00:06:03,960 and then we'll run the application. 128 00:06:03,960 --> 00:06:06,810 So let's take a look at the code and run the application. 129 00:06:08,028 --> 00:06:10,620 Okay, so mytypes, we've seen it before. 130 00:06:10,620 --> 00:06:12,330 There's my employee structure. 131 00:06:12,330 --> 00:06:16,350 Main declares the mytypes module, and it imports, 132 00:06:16,350 --> 00:06:18,900 it declares all the other modules as well for the demo. 133 00:06:18,900 --> 00:06:21,150 And we're currently looking at this piece of code here, 134 00:06:21,150 --> 00:06:24,030 demo_struct_pass_reference. 135 00:06:24,030 --> 00:06:26,130 So let's uncover that statement 136 00:06:26,130 --> 00:06:29,703 and let's have a look at the code. 137 00:06:31,170 --> 00:06:36,170 So I've got two functions plus the kind of driving code 138 00:06:36,810 --> 00:06:40,710 at the top, a function that receives an immutable reference 139 00:06:40,710 --> 00:06:44,460 and a function that receives a mutable reference. 140 00:06:44,460 --> 00:06:46,560 So up here in main, 141 00:06:46,560 --> 00:06:51,030 I've got a mutable employee, Jane, 1,000, true. 142 00:06:51,030 --> 00:06:53,280 Even though the employee is mutable, 143 00:06:53,280 --> 00:06:56,400 it's still possible to pass an immutable reference. 144 00:06:56,400 --> 00:06:59,430 So whilst the object is actually mutable, 145 00:06:59,430 --> 00:07:03,690 this function is like a const function really in C++. 146 00:07:03,690 --> 00:07:06,810 That function, this function here on line 14 147 00:07:06,810 --> 00:07:08,640 treats the employee as const 148 00:07:08,640 --> 00:07:11,070 or immutable, do in the print function. 149 00:07:11,070 --> 00:07:13,260 It just prints but doesn't change. 150 00:07:13,260 --> 00:07:17,250 So it receives an immutable reference. 151 00:07:17,250 --> 00:07:18,510 And I can print out the name 152 00:07:18,510 --> 00:07:20,580 and the salary and the full-time status. 153 00:07:20,580 --> 00:07:23,460 I can either, let me just give myself a bit more space here, 154 00:07:23,460 --> 00:07:26,340 I can either use explicit dereferencing, 155 00:07:26,340 --> 00:07:28,710 give me the contents of the reference, give me the contents 156 00:07:28,710 --> 00:07:32,310 of the object, name, dereference explicitly, 157 00:07:32,310 --> 00:07:35,640 dereference explicitly, or you can do it implicitly, 158 00:07:35,640 --> 00:07:39,390 implicitly dereference e to give me back the structure, 159 00:07:39,390 --> 00:07:41,700 and give me the name and the salary 160 00:07:41,700 --> 00:07:43,500 and the full-time status. 161 00:07:43,500 --> 00:07:45,060 I just wanted to remind you here 162 00:07:45,060 --> 00:07:47,610 that you can either use explicit dereferencing 163 00:07:47,610 --> 00:07:50,460 if you get paid per keystroke, 164 00:07:50,460 --> 00:07:52,680 or you can just use implicit dereferencing, 165 00:07:52,680 --> 00:07:54,813 which is much easier on the eye. 166 00:07:57,510 --> 00:08:00,330 So that was the print function. 167 00:08:00,330 --> 00:08:04,320 And then the reward_employee, it takes a mutable reference 168 00:08:04,320 --> 00:08:07,980 to the employee and it gives the employee 169 00:08:07,980 --> 00:08:11,520 a 500 pound salary increment 170 00:08:11,520 --> 00:08:14,370 using the explicit dereference syntax 171 00:08:14,370 --> 00:08:18,870 and a further 250 pound just to complete the user's good day 172 00:08:18,870 --> 00:08:21,210 using implicit dereference. 173 00:08:21,210 --> 00:08:25,050 So I call that function with a mutable reference. 174 00:08:25,050 --> 00:08:27,030 Oh, and then I print the employee afterwards 175 00:08:27,030 --> 00:08:28,323 with their new salary. 176 00:08:29,730 --> 00:08:31,730 Well, let's run it and see what happens. 177 00:08:33,750 --> 00:08:35,043 Cargo run. 178 00:08:38,430 --> 00:08:42,240 So the initial employee salary using explicit 179 00:08:42,240 --> 00:08:45,603 and implicit dereferencing is 1,000. 180 00:08:46,470 --> 00:08:51,390 And then we reward the employee with a 750 pound pay rise. 181 00:08:51,390 --> 00:08:53,730 And then we print the details again 182 00:08:53,730 --> 00:08:56,480 and you can see that the details have been incremented. 183 00:08:57,840 --> 00:08:58,673 There we go. 184 00:08:58,673 --> 00:09:00,390 So this is the main way 185 00:09:00,390 --> 00:09:03,000 in which you pass structures into a function. 186 00:09:03,000 --> 00:09:08,000 You pass 'em by reference, either immutable if you can, 187 00:09:08,340 --> 00:09:10,623 or mutable if you have to. 188 00:09:11,520 --> 00:09:15,693 So passing objects by reference is the natural way to do it.