1 00:00:06,648 --> 00:00:07,650 - In this section, 2 00:00:07,650 --> 00:00:10,230 we're going to dig deeper into how strings work. 3 00:00:10,230 --> 00:00:12,540 We've talked a little bit about strings already, 4 00:00:12,540 --> 00:00:14,520 and now that we understand borrowing, 5 00:00:14,520 --> 00:00:16,500 we're going to look at it in more detail. 6 00:00:16,500 --> 00:00:18,690 Quite a confusing area for Rust developers, 7 00:00:18,690 --> 00:00:19,620 when they get started, 8 00:00:19,620 --> 00:00:23,430 the fact that Rust actually has two different string types. 9 00:00:23,430 --> 00:00:26,310 First of all, it has string as a structure. 10 00:00:26,310 --> 00:00:29,310 This is a standard structure in Rust 11 00:00:29,310 --> 00:00:32,790 and it's the primary way that you create strings. 12 00:00:32,790 --> 00:00:35,850 When you create the string object, it owns text, 13 00:00:35,850 --> 00:00:38,160 it owns the text allocated on the heap. 14 00:00:38,160 --> 00:00:42,600 So a string object would own text on the heap 15 00:00:42,600 --> 00:00:44,340 and potentially could change it, 16 00:00:44,340 --> 00:00:45,750 you know, if it was mutable, 17 00:00:45,750 --> 00:00:48,360 and would be responsible for de-allocating it 18 00:00:48,360 --> 00:00:50,250 when the string is dropped. 19 00:00:50,250 --> 00:00:51,540 So this is the main way 20 00:00:51,540 --> 00:00:53,640 of holding text in your application 21 00:00:53,640 --> 00:00:56,010 that you want to own and change. 22 00:00:56,010 --> 00:00:57,210 That's the way to do it. 23 00:00:58,170 --> 00:01:01,860 But there's another type called str, 24 00:01:01,860 --> 00:01:03,300 with a lowercase S, 25 00:01:03,300 --> 00:01:05,730 and this is a primitive type in Rust. 26 00:01:05,730 --> 00:01:08,040 It's a fact pointer, basically. 27 00:01:08,040 --> 00:01:11,730 It basically represents a slice of text somewhere. 28 00:01:11,730 --> 00:01:13,320 It doesn't own the text, 29 00:01:13,320 --> 00:01:15,810 it's just a slice of text. 30 00:01:15,810 --> 00:01:20,250 So a str would be basically like a pointer 31 00:01:20,250 --> 00:01:25,230 to a part of some text allocated elsewhere. 32 00:01:25,230 --> 00:01:28,410 It just points to a bite, like the letter E, 33 00:01:28,410 --> 00:01:29,700 and it knows how big it is, 34 00:01:29,700 --> 00:01:30,990 but it doesn't own the text. 35 00:01:30,990 --> 00:01:34,800 It's just an observer of that little window of text. 36 00:01:34,800 --> 00:01:38,050 So we need to discuss how the string structure 37 00:01:39,450 --> 00:01:42,840 and the str slice interact with each other, 38 00:01:42,840 --> 00:01:44,520 because they do interact with each other. 39 00:01:44,520 --> 00:01:47,820 So first of all, let's take a look at this example. 40 00:01:47,820 --> 00:01:51,120 I'm going to borrow a string object. 41 00:01:51,120 --> 00:01:54,360 So first of all, I've declared a string object, obj, 42 00:01:54,360 --> 00:01:56,370 and here it is, it's a string object 43 00:01:56,370 --> 00:02:00,390 and it contains the text hello, right here. 44 00:02:00,390 --> 00:02:02,070 And then in red, you can see here, 45 00:02:02,070 --> 00:02:03,900 I've taken a reference to the object 46 00:02:03,900 --> 00:02:05,760 and I've stored that reference in S. 47 00:02:05,760 --> 00:02:08,580 So let's think about the data types involved here. 48 00:02:08,580 --> 00:02:11,070 So first of all, when I say &obj 49 00:02:11,070 --> 00:02:13,290 that's taken a reference to a string, 50 00:02:13,290 --> 00:02:14,370 or as a Rust developer, 51 00:02:14,370 --> 00:02:16,320 I would say we're borrowing the string. 52 00:02:16,320 --> 00:02:19,260 So the type of &obj 53 00:02:19,260 --> 00:02:22,410 is a string reference, okay? 54 00:02:22,410 --> 00:02:25,140 So this is a string reference. 55 00:02:25,140 --> 00:02:26,670 And then what about S? 56 00:02:26,670 --> 00:02:28,830 I haven't typed it explicitly. 57 00:02:28,830 --> 00:02:33,120 So implicitly it will also be a string reference. 58 00:02:33,120 --> 00:02:36,130 So S is a reference to the whole string 59 00:02:38,100 --> 00:02:40,830 like that, okay? 60 00:02:40,830 --> 00:02:43,260 And you know, if I'd set this up as being mutable 61 00:02:43,260 --> 00:02:47,100 then I could have modified the whole string object via S. 62 00:02:47,100 --> 00:02:49,770 So that's quite straightforward actually. 63 00:02:49,770 --> 00:02:51,360 Let's take things a step further 64 00:02:51,360 --> 00:02:52,710 and see what happens 65 00:02:52,710 --> 00:02:55,650 if you use this syntax, which you can. 66 00:02:55,650 --> 00:02:57,420 Let's see what happens here. 67 00:02:57,420 --> 00:03:00,540 So again, obj is a string object. 68 00:03:00,540 --> 00:03:01,950 So let's just draw that here, 69 00:03:01,950 --> 00:03:03,663 holds the text, hello, 70 00:03:05,850 --> 00:03:09,540 like so that's the text on the heap. 71 00:03:09,540 --> 00:03:11,340 Let's consider the types involved 72 00:03:11,340 --> 00:03:12,720 in my red statement here. 73 00:03:12,720 --> 00:03:15,420 So first of all, on the right hand side, 74 00:03:15,420 --> 00:03:17,880 I've taken a reference to a string object, okay? 75 00:03:17,880 --> 00:03:20,040 So that kind of is like a reference 76 00:03:20,040 --> 00:03:20,990 to the whole string 77 00:03:22,080 --> 00:03:26,370 but you'll notice that when I declare the variable, 78 00:03:26,370 --> 00:03:28,500 when I , oops, let me just draw my object again. 79 00:03:28,500 --> 00:03:30,150 When I declare the variable here 80 00:03:30,150 --> 00:03:33,180 I give it a type &str, okay? 81 00:03:33,180 --> 00:03:35,100 So that's a string slice. 82 00:03:35,100 --> 00:03:40,080 So technically, S is a slice into the string. 83 00:03:40,080 --> 00:03:42,750 Initially, it's like a fat pointer, 84 00:03:42,750 --> 00:03:44,070 well, it's a fat pointer. 85 00:03:44,070 --> 00:03:47,220 S will be a pointer 86 00:03:47,220 --> 00:03:49,620 to the first bite in the string 87 00:03:49,620 --> 00:03:52,410 and it'll know that the string is five characters. 88 00:03:52,410 --> 00:03:55,380 So at the moment, I've set up S 89 00:03:55,380 --> 00:04:00,003 to refer to this slice of text effectively, 90 00:04:01,350 --> 00:04:03,180 but what I could do 91 00:04:03,180 --> 00:04:06,540 is I could change S to be a sub-portion. 92 00:04:06,540 --> 00:04:09,930 So for example, I could change my slice. 93 00:04:09,930 --> 00:04:11,850 So that instead of being the whole string, 94 00:04:11,850 --> 00:04:14,410 maybe it points to the letter E 95 00:04:15,330 --> 00:04:18,900 and maybe it only holds two characters, okay? 96 00:04:18,900 --> 00:04:21,480 So as far as the string slice is concerned now, 97 00:04:21,480 --> 00:04:25,850 the string slice would only be this bit here, okay? 98 00:04:25,850 --> 00:04:28,980 So you can see where the terminology a slice comes, 99 00:04:28,980 --> 00:04:30,750 the string is hello, 100 00:04:30,750 --> 00:04:33,123 but you can look at a little slice of it, 101 00:04:33,990 --> 00:04:35,943 just the few characters if you want to. 102 00:04:38,010 --> 00:04:40,230 Right, now, here's an important thing. 103 00:04:40,230 --> 00:04:43,470 Here's a fact, the compiler 104 00:04:43,470 --> 00:04:46,620 is capable of automatically converting 105 00:04:46,620 --> 00:04:50,403 a string reference into a string slice. 106 00:04:51,600 --> 00:04:54,933 So that's needs further investigation. 107 00:04:56,040 --> 00:04:58,440 If you borrow a string object, 108 00:04:58,440 --> 00:05:00,873 in other words if you say something like a &S1, 109 00:05:04,290 --> 00:05:07,830 you can assign it into a str slice. 110 00:05:07,830 --> 00:05:10,770 Okay, so you could declare a variable, 111 00:05:10,770 --> 00:05:15,770 let I call it string slice 1, 112 00:05:16,110 --> 00:05:18,753 as a string slice, &str. 113 00:05:21,240 --> 00:05:23,910 Like that, and that's actually exactly what we did 114 00:05:23,910 --> 00:05:25,830 on the previous slide. 115 00:05:25,830 --> 00:05:28,200 I've got a string object, S1 116 00:05:28,200 --> 00:05:31,083 that holds the actual text, hello, let's say. 117 00:05:31,950 --> 00:05:34,320 And then on the left hand side, 118 00:05:34,320 --> 00:05:35,760 I've taken a reference to the string, 119 00:05:35,760 --> 00:05:38,940 but I've stored it in a string slice. 120 00:05:38,940 --> 00:05:41,460 So SS1, string slice 1 121 00:05:41,460 --> 00:05:43,920 isn't a pointer to the whole string, 122 00:05:43,920 --> 00:05:46,500 it is rather a string slice 123 00:05:46,500 --> 00:05:49,140 into the actual text like that. 124 00:05:49,140 --> 00:05:51,390 And it knows not only the pointer 125 00:05:51,390 --> 00:05:55,200 but how big the text is as well, like that. 126 00:05:55,200 --> 00:05:57,570 So there's an automatic conversion 127 00:05:57,570 --> 00:06:01,710 between a string reference and a string slice. 128 00:06:01,710 --> 00:06:03,660 And that's what we've got here. 129 00:06:03,660 --> 00:06:07,050 So we've got the object, which is hello, 130 00:06:07,050 --> 00:06:08,340 and this is a, 131 00:06:08,340 --> 00:06:11,610 this type here is &String. 132 00:06:11,610 --> 00:06:14,280 It's a reference to string object. 133 00:06:14,280 --> 00:06:17,400 I can quite happily assign it to this variable 134 00:06:17,400 --> 00:06:18,630 on the left hand side, 135 00:06:18,630 --> 00:06:20,883 which has type string slice. 136 00:06:21,990 --> 00:06:26,550 Okay, so S basically refers just into the text itself 137 00:06:26,550 --> 00:06:29,640 not to the actual string object itself. 138 00:06:29,640 --> 00:06:31,470 So you have to kind of think about this a little bit 139 00:06:31,470 --> 00:06:33,820 and kind of work the idea through in your mind. 140 00:06:34,860 --> 00:06:38,730 It's quite handy when you write in functions 141 00:06:38,730 --> 00:06:41,673 because if you have a function that takes this type, 142 00:06:42,540 --> 00:06:44,670 you can either pass in literal text 143 00:06:44,670 --> 00:06:47,403 or you can pass in a whole string object. 144 00:06:48,540 --> 00:06:51,090 So that can be quite useful. 145 00:06:51,090 --> 00:06:52,920 So let's take a look at that. 146 00:06:52,920 --> 00:06:54,690 Here's a literal text. 147 00:06:54,690 --> 00:06:56,610 When you have literal text, 148 00:06:56,610 --> 00:07:00,360 the technical data type of literal text 149 00:07:00,360 --> 00:07:03,720 is a string reference, a string slice. 150 00:07:03,720 --> 00:07:05,940 The static keyword here 151 00:07:05,940 --> 00:07:08,010 is just indicated in the lifetime 152 00:07:08,010 --> 00:07:10,770 of the text is permanently allocated. 153 00:07:10,770 --> 00:07:13,140 When you have a string literal like hello 154 00:07:13,140 --> 00:07:14,730 it's never gonna disappear. 155 00:07:14,730 --> 00:07:16,560 It's just fixed memory. 156 00:07:16,560 --> 00:07:18,810 So it shows, it just indicates 157 00:07:18,810 --> 00:07:20,070 that the lifetime of the text 158 00:07:20,070 --> 00:07:21,420 you're referring to is static 159 00:07:21,420 --> 00:07:24,540 will always be there, okay? 160 00:07:24,540 --> 00:07:26,700 So this is a literal text. 161 00:07:26,700 --> 00:07:28,413 This here is a string slice. 162 00:07:29,310 --> 00:07:32,940 Technically S is, would look like this. 163 00:07:32,940 --> 00:07:35,940 It would have a pointer to the letter H 164 00:07:35,940 --> 00:07:39,330 and it would know that there are five letters in H, okay? 165 00:07:39,330 --> 00:07:40,683 So that's basically what the string slice is. 166 00:07:40,683 --> 00:07:43,173 It's points to the string literal. 167 00:07:44,310 --> 00:07:46,260 So let's see an example 168 00:07:46,260 --> 00:07:47,460 to put this into practice, 169 00:07:47,460 --> 00:07:52,200 lesson07_borrowing demo_string_slice_intro. 170 00:07:52,200 --> 00:07:54,510 We'll look at the code and then we'll run it as usual. 171 00:07:54,510 --> 00:07:56,010 Let's see. 172 00:07:56,010 --> 00:07:59,670 So here's the code in my main.rs. 173 00:07:59,670 --> 00:08:04,670 I'm going to uncomment demo_string_slice_intro. 174 00:08:05,220 --> 00:08:06,963 And here it is. 175 00:08:07,890 --> 00:08:10,680 Right, so I've got a couple of functions, 176 00:08:10,680 --> 00:08:13,110 string slices with objects 177 00:08:13,110 --> 00:08:15,300 and string slices with literals. 178 00:08:15,300 --> 00:08:17,460 So here we go. 179 00:08:17,460 --> 00:08:20,310 Here is my string object. 180 00:08:20,310 --> 00:08:22,740 And this is a, 181 00:08:22,740 --> 00:08:26,910 this variable here implicitly 182 00:08:26,910 --> 00:08:28,923 is a &String. 183 00:08:30,120 --> 00:08:32,370 I can take that 184 00:08:32,370 --> 00:08:35,760 and also refer it to a string slice. 185 00:08:35,760 --> 00:08:38,500 So S1 has type 186 00:08:40,470 --> 00:08:41,907 reference to string. 187 00:08:41,907 --> 00:08:44,640 And S2 explicitly 188 00:08:44,640 --> 00:08:48,390 has type string slice, okay? 189 00:08:48,390 --> 00:08:50,700 So you can take a reference to a string object 190 00:08:50,700 --> 00:08:54,720 and store it in a string reference, 191 00:08:54,720 --> 00:08:57,150 or you can store it in a string slice. 192 00:08:57,150 --> 00:08:59,880 And in both cases it would print hello. 193 00:08:59,880 --> 00:09:03,270 And then in my second example, 194 00:09:03,270 --> 00:09:06,600 here this is a string literal. 195 00:09:06,600 --> 00:09:09,600 And a string literal implicitly is a string slice. 196 00:09:09,600 --> 00:09:11,130 When you assign a string literal 197 00:09:11,130 --> 00:09:14,310 this variable here is implicitly a slice. 198 00:09:14,310 --> 00:09:16,230 It knows the address of the H 199 00:09:16,230 --> 00:09:18,660 and it knows how many characters there are, five. 200 00:09:18,660 --> 00:09:20,460 And if you want to be explicit about it, 201 00:09:20,460 --> 00:09:22,680 you could say, here's a string literal 202 00:09:22,680 --> 00:09:25,770 and let's assign it to a string slice. 203 00:09:25,770 --> 00:09:30,270 In practice, nobody ever bothers typing explicitly 204 00:09:30,270 --> 00:09:31,920 a string literal, okay? 205 00:09:31,920 --> 00:09:34,470 It's quite okay to leave it like this. 206 00:09:34,470 --> 00:09:36,240 So in practice, I wouldn't bother 207 00:09:36,240 --> 00:09:38,970 with explicit typing because it's just too much effort 208 00:09:38,970 --> 00:09:42,360 unless you really wanted to prove the point, like so. 209 00:09:42,360 --> 00:09:45,993 Right, so when I run the application it's gonna work. 210 00:09:47,790 --> 00:09:49,410 What we're gonna do in the next section 211 00:09:49,410 --> 00:09:50,970 is we're gonna see some applications 212 00:09:50,970 --> 00:09:53,700 of string slices in practice. 213 00:09:53,700 --> 00:09:55,000 Let's just run it for now. 214 00:09:59,294 --> 00:10:00,270 There we go. 215 00:10:00,270 --> 00:10:02,100 Right, so to summarize 216 00:10:02,100 --> 00:10:04,590 this introduction to string slices, 217 00:10:04,590 --> 00:10:06,663 you start off with a real string object. 218 00:10:07,950 --> 00:10:11,370 You can take a slice of that string object. 219 00:10:11,370 --> 00:10:14,880 You can also take a slice from string literal, okay? 220 00:10:14,880 --> 00:10:17,640 So S3 is a string slice. 221 00:10:17,640 --> 00:10:19,800 S4 is a string slice, 222 00:10:19,800 --> 00:10:21,540 a slice into existing text, 223 00:10:21,540 --> 00:10:24,750 as is S2, it's a slice into the text 224 00:10:24,750 --> 00:10:26,280 of an existing string object. 225 00:10:26,280 --> 00:10:28,020 So that gives you an introduction. 226 00:10:28,020 --> 00:10:29,430 And what we'll do in the next lesson 227 00:10:29,430 --> 00:10:30,630 is go into it in more detail 228 00:10:30,630 --> 00:10:32,280 and see why this might be useful.