1 00:00:06,600 --> 00:00:09,120 - In the first three sections in this lesson, 2 00:00:09,120 --> 00:00:13,230 we've been showing how to pass parameters into a function. 3 00:00:13,230 --> 00:00:15,720 And so the last three sections in the chapter, 4 00:00:15,720 --> 00:00:18,990 we are going to see how to return something from a function. 5 00:00:18,990 --> 00:00:22,500 So we'll kick off by looking at how to return a value. 6 00:00:22,500 --> 00:00:24,900 Then we'll see how to return a reference, 7 00:00:24,900 --> 00:00:26,280 and then finally we'll see how 8 00:00:26,280 --> 00:00:28,590 to return a mutable reference. 9 00:00:28,590 --> 00:00:31,140 Okay? So first of all, the general syntax. 10 00:00:31,140 --> 00:00:33,300 When you want to return something from a function, 11 00:00:33,300 --> 00:00:35,790 this is how you specify the return type. 12 00:00:35,790 --> 00:00:38,490 This function here takes some parameters 13 00:00:38,490 --> 00:00:39,904 and then you say arrow 14 00:00:39,904 --> 00:00:42,780 and then the type that the function returns. 15 00:00:42,780 --> 00:00:45,600 Okay? So that's the return type from the function. 16 00:00:45,600 --> 00:00:47,790 If you don't specify a return type, 17 00:00:47,790 --> 00:00:52,230 so in other words, if you didn't have anything here, 18 00:00:52,230 --> 00:00:55,620 then implicitly the function has no return value 19 00:00:55,620 --> 00:00:58,080 and that would be like void in other languages. 20 00:00:58,080 --> 00:00:59,610 So as it stands now, 21 00:00:59,610 --> 00:01:01,410 the function doesn't return a value. 22 00:01:02,400 --> 00:01:03,780 Right, the next thing to consider 23 00:01:03,780 --> 00:01:06,420 is how do you actually return a value of that type? 24 00:01:06,420 --> 00:01:09,090 Well, you use the return keyword, no surprise there. 25 00:01:09,090 --> 00:01:12,663 So this function indicates that it returns some type. 26 00:01:13,950 --> 00:01:16,753 So then you must have in your function 27 00:01:16,753 --> 00:01:20,850 a return statement which returns some value of that type. 28 00:01:20,850 --> 00:01:24,390 And remember, Rust is quite fussy about type correspondence. 29 00:01:24,390 --> 00:01:27,840 You've gotta return the value of that actual type. 30 00:01:27,840 --> 00:01:29,940 There is a shorthand syntax. 31 00:01:29,940 --> 00:01:34,860 You can do this, if the last bit of your function 32 00:01:34,860 --> 00:01:39,630 is an expression, okay, so not a statement. 33 00:01:39,630 --> 00:01:43,110 In other words, no semicolon, if it's just an expression, 34 00:01:43,110 --> 00:01:46,583 so there's no semicolon here, there isn't, okay? 35 00:01:48,720 --> 00:01:51,630 Then this expression is implicitly taken 36 00:01:51,630 --> 00:01:53,190 to be the return value. 37 00:01:53,190 --> 00:01:55,316 So this is what most Rust developers do. 38 00:01:55,316 --> 00:01:57,960 They just have a value at the end of the function 39 00:01:57,960 --> 00:02:01,233 and that's implicitly the return value of that type. 40 00:02:02,580 --> 00:02:05,910 Okay, so first of all, then how do you return a value? 41 00:02:05,910 --> 00:02:08,700 It depends on whether it's a copyable type, 42 00:02:08,700 --> 00:02:13,020 like int32, or a non copyable type like string. 43 00:02:13,020 --> 00:02:17,010 So first of all let's discuss returning a copyable value, 44 00:02:17,010 --> 00:02:21,330 a type which implements the copy trait like i32. 45 00:02:21,330 --> 00:02:23,910 So in that case the value that you return 46 00:02:23,910 --> 00:02:27,150 will be bit copied to the calling function. 47 00:02:27,150 --> 00:02:30,000 It's quite straightforward. So here's an example. 48 00:02:30,000 --> 00:02:34,080 Starting at the top, I have some higher level function. 49 00:02:34,080 --> 00:02:35,970 I come in here, I call f1 50 00:02:35,970 --> 00:02:37,967 So we call f1, 51 00:02:37,967 --> 00:02:41,523 and f1 indicates that it's going to return an i32. 52 00:02:43,020 --> 00:02:48,020 So in the function we do indeed return an i32. 53 00:02:48,196 --> 00:02:51,903 So n here is a local variable. It has the value 42. 54 00:02:52,800 --> 00:02:55,080 When we return n from the function, 55 00:02:55,080 --> 00:02:59,160 that value n is bit copied up to here. 56 00:02:59,160 --> 00:03:01,683 Okay? So that value then disappears, 57 00:03:02,640 --> 00:03:06,690 and the variable in our function up here is a copy 58 00:03:06,690 --> 00:03:08,880 of the value that was returned. 59 00:03:08,880 --> 00:03:12,450 Okay? So basically the value here is bit copied 60 00:03:12,450 --> 00:03:14,010 into the return like so, 61 00:03:14,010 --> 00:03:17,490 because i32 implements the copy trait. 62 00:03:17,490 --> 00:03:19,320 So that's nice and easy. 63 00:03:19,320 --> 00:03:21,090 And now we are gonna consider what happens 64 00:03:21,090 --> 00:03:23,640 when you return a non copyable value, 65 00:03:23,640 --> 00:03:24,690 something like a string, 66 00:03:24,690 --> 00:03:27,060 something which doesn't implement the copy trait. 67 00:03:27,060 --> 00:03:29,820 So in that case, when you return, for example, 68 00:03:29,820 --> 00:03:32,040 a string from a function, 69 00:03:32,040 --> 00:03:36,870 Rust moves ownership from the function back to the caller. 70 00:03:36,870 --> 00:03:40,778 The caller then becomes the owner of that string. 71 00:03:40,778 --> 00:03:43,020 Right. So here's an example again, 72 00:03:43,020 --> 00:03:45,000 let's take this example from the top. 73 00:03:45,000 --> 00:03:49,413 Here is my sum higher level function, and I call f2. 74 00:03:50,556 --> 00:03:54,810 f2 indicates that it's going to return a string object, 75 00:03:54,810 --> 00:03:56,310 which is nice. 76 00:03:56,310 --> 00:04:00,780 So inside the function, I create the string object, s, 77 00:04:00,780 --> 00:04:05,780 let's draw it here, and it contains the text, "hello" 78 00:04:07,530 --> 00:04:10,140 like so, and when I return s, 79 00:04:10,140 --> 00:04:12,660 basically it'll take a bit copy 80 00:04:12,660 --> 00:04:15,600 of this then and pass it into here. 81 00:04:15,600 --> 00:04:19,080 So this string variable here, which I've also called s, 82 00:04:19,080 --> 00:04:23,970 that also has a pointer to the underlying text. 83 00:04:23,970 --> 00:04:25,830 And the original string object here 84 00:04:25,830 --> 00:04:28,590 loses ownership of that text. 85 00:04:28,590 --> 00:04:32,430 So effectively this then has relinquished control 86 00:04:32,430 --> 00:04:35,853 and transferred control back up to this string here. 87 00:04:37,410 --> 00:04:40,440 Okay? So the string object that was owned here, 88 00:04:40,440 --> 00:04:43,080 effectively ownership gets transferred 89 00:04:43,080 --> 00:04:45,210 up to the calling function. 90 00:04:45,210 --> 00:04:48,093 And this function now owns the string, 91 00:04:49,470 --> 00:04:50,970 which I guess means that 92 00:04:50,970 --> 00:04:53,100 at the end of some higher level function 93 00:04:53,100 --> 00:04:55,770 when this outer string goes outta scope, 94 00:04:55,770 --> 00:04:58,530 at that point the string will be dropped 95 00:04:58,530 --> 00:05:00,570 and the text will be deleted. 96 00:05:00,570 --> 00:05:02,880 Okay? So when you return the value, 97 00:05:02,880 --> 00:05:06,030 it'll either do a bit copy if it's a copy type 98 00:05:06,030 --> 00:05:07,920 or it'll move ownership 99 00:05:07,920 --> 00:05:10,860 into the recipient return value basically, 100 00:05:10,860 --> 00:05:14,160 and the return value then owns that data. 101 00:05:14,160 --> 00:05:19,050 Right, one small caveat, this doesn't work. 102 00:05:19,050 --> 00:05:21,840 Imagine you tried to return a string literal. 103 00:05:21,840 --> 00:05:22,890 The purpose of this function, 104 00:05:22,890 --> 00:05:25,590 I've called it bad funk because it won't compile, 105 00:05:25,590 --> 00:05:29,070 it was hoping to return a string object, okay? 106 00:05:29,070 --> 00:05:32,730 But, and what it tries to do, it takes the mark, 107 00:05:32,730 --> 00:05:34,500 like the exam mark, and it hopes to be return 108 00:05:34,500 --> 00:05:38,700 either this string literal or this string literal, 109 00:05:38,700 --> 00:05:41,970 but it doesn't work because a string literal 110 00:05:41,970 --> 00:05:45,270 is a reference, a string reference. 111 00:05:45,270 --> 00:05:48,778 There's no automatic conversion from a string reference 112 00:05:48,778 --> 00:05:50,340 to a string object. 113 00:05:50,340 --> 00:05:53,759 It was hoping to return a whole string, not a string slice. 114 00:05:53,759 --> 00:05:56,160 So that syntax wouldn't work. 115 00:05:56,160 --> 00:05:57,990 If you really did want to be return a string, 116 00:05:57,990 --> 00:06:02,990 you'd have to say string colon colon from pass, okay? 117 00:06:06,810 --> 00:06:10,440 In which case this string object would then be copied back 118 00:06:10,440 --> 00:06:13,287 to the caller and the caller would then adopt ownership 119 00:06:13,287 --> 00:06:14,850 of that string. 120 00:06:14,850 --> 00:06:19,407 So if you do want to return references like a string slice, 121 00:06:19,407 --> 00:06:21,420 we'll talk about that later on. 122 00:06:21,420 --> 00:06:24,570 In the next demo, we'll see how to return a reference 123 00:06:24,570 --> 00:06:26,970 if that's what you really want to do. 124 00:06:26,970 --> 00:06:28,290 But for now, let's just have a look 125 00:06:28,290 --> 00:06:30,153 at the demo for returning the value. 126 00:06:31,080 --> 00:06:35,160 So here we are, this is my lesson eight functions demo. 127 00:06:35,160 --> 00:06:38,910 In the main code, let's uncomment the relevant demo, 128 00:06:38,910 --> 00:06:41,730 demo return in value, that one there, 129 00:06:41,730 --> 00:06:44,163 and it's here. 130 00:06:45,750 --> 00:06:47,973 So let's have a look at the code. 131 00:06:48,840 --> 00:06:50,460 In my do it function 132 00:06:50,460 --> 00:06:54,390 I call the function that returns a copyable type. 133 00:06:54,390 --> 00:06:55,980 So that's this function here. 134 00:06:55,980 --> 00:06:58,920 It declares a local integer 135 00:06:58,920 --> 00:07:00,510 and then when it returns the integer, 136 00:07:00,510 --> 00:07:03,660 the bits of this integer are bit copied 137 00:07:03,660 --> 00:07:05,160 into the recipient function. 138 00:07:05,160 --> 00:07:07,680 So that's effectively a copy. 139 00:07:07,680 --> 00:07:09,060 That's the first function. 140 00:07:09,060 --> 00:07:10,470 And then the second function call 141 00:07:10,470 --> 00:07:13,680 function returning a non copyable type, 142 00:07:13,680 --> 00:07:15,330 well that's this one here. 143 00:07:15,330 --> 00:07:18,780 And it returns a string object by movement. 144 00:07:18,780 --> 00:07:20,670 Here's my local string. 145 00:07:20,670 --> 00:07:24,030 When I return that string, this string, 146 00:07:24,030 --> 00:07:26,490 the ownership of that string will be moved 147 00:07:26,490 --> 00:07:28,680 into the return value here. 148 00:07:28,680 --> 00:07:31,530 Okay? So this string, this variable here, 149 00:07:31,530 --> 00:07:33,660 adopts ownership of the text. 150 00:07:33,660 --> 00:07:35,640 And this is now the owner 151 00:07:35,640 --> 00:07:38,040 which means that when s goes out of scope, 152 00:07:38,040 --> 00:07:40,803 that's when the string will be actually de-allocated. 153 00:07:41,760 --> 00:07:44,036 And then finally, as I was saying, 154 00:07:44,036 --> 00:07:47,950 if you tried to return a string literal from a function 155 00:07:48,900 --> 00:07:51,480 when the function was actually expecting a whole string, 156 00:07:51,480 --> 00:07:53,178 then this wouldn't compile. 157 00:07:53,178 --> 00:07:56,370 I'll just uncomment this code just to show you the error 158 00:07:56,370 --> 00:07:58,380 and then we'll comment the code back up again 159 00:07:58,380 --> 00:07:59,670 and run it properly. 160 00:07:59,670 --> 00:08:01,953 So let's just open a quick terminal window. 161 00:08:02,790 --> 00:08:04,500 I'll just do a quick cargo check. 162 00:08:04,500 --> 00:08:08,403 I'm expecting a compiler error on line 27. 163 00:08:09,990 --> 00:08:10,920 Well look at that. 164 00:08:10,920 --> 00:08:15,920 So it says, "On line 27, you are trying to return a," 165 00:08:16,080 --> 00:08:19,170 well, according to the function, it was expecting 166 00:08:19,170 --> 00:08:23,396 that you're going to return a string object. 167 00:08:23,396 --> 00:08:26,970 But instead, you've either returned a string literal, 168 00:08:26,970 --> 00:08:30,930 sorry a string literal here, like a string slice, 169 00:08:30,930 --> 00:08:33,300 or it's gonna return this string slice. 170 00:08:33,300 --> 00:08:35,790 In either case, it's not a whole string object. 171 00:08:35,790 --> 00:08:37,620 It considers whether you should call 172 00:08:37,620 --> 00:08:38,820 the two string function. 173 00:08:38,820 --> 00:08:41,640 If you have a string literal and you call two string, 174 00:08:41,640 --> 00:08:44,250 it actually converts into an actual string object 175 00:08:44,250 --> 00:08:46,470 and that would actually work here. 176 00:08:46,470 --> 00:08:48,667 But anyway, let's just comment that out 177 00:08:48,667 --> 00:08:51,090 (typing) 178 00:08:51,090 --> 00:08:55,380 and let's just run the code that we hope will actually work. 179 00:08:55,380 --> 00:08:57,918 So I'll save the file and I'll run it. 180 00:08:57,918 --> 00:08:59,700 (typing) 181 00:08:59,700 --> 00:09:01,900 So I'm hopefully expecting this to work now. 182 00:09:03,120 --> 00:09:04,920 Okay, yes, it's worked okay. 183 00:09:04,920 --> 00:09:07,320 So initially I called the function 184 00:09:07,320 --> 00:09:12,223 that returned a copy of n, the number 42. 185 00:09:13,290 --> 00:09:16,170 And then in the second case, I called the function 186 00:09:16,170 --> 00:09:18,390 which had a local string 187 00:09:18,390 --> 00:09:20,943 and moved ownership of that string into here. 188 00:09:21,990 --> 00:09:24,000 Okay? And that's the string, "Hello". 189 00:09:24,000 --> 00:09:26,310 Incidentally, if you wanted to simplify this code, 190 00:09:26,310 --> 00:09:28,830 if you really did want to write something that simple 191 00:09:28,830 --> 00:09:32,790 then I could have just said 42. 192 00:09:32,790 --> 00:09:34,950 Okay? And without the semicolon. 193 00:09:34,950 --> 00:09:38,520 That's an expression, that's implicitly the return value. 194 00:09:38,520 --> 00:09:41,970 And likewise here, if this really was all I wanted to do, 195 00:09:41,970 --> 00:09:43,980 I could have just written it like this, 196 00:09:43,980 --> 00:09:45,870 again without the semicolon, 197 00:09:45,870 --> 00:09:48,810 so it has to be an expression, not a statement. 198 00:09:48,810 --> 00:09:51,420 And then I could have got rid of that statement there. 199 00:09:51,420 --> 00:09:54,060 So if you have a dangling expression 200 00:09:54,060 --> 00:09:57,030 it is implicitly taken as the return value. 201 00:09:57,030 --> 00:09:58,890 So that would also work. 202 00:09:58,890 --> 00:10:01,743 Let's just prove the point, run it again, 203 00:10:02,790 --> 00:10:03,750 and it works. 204 00:10:03,750 --> 00:10:04,583 Magic.