1 00:00:00,000 --> 00:00:08,166 [No Audio] 2 00:00:08,167 --> 00:00:10,829 This tutorial is about Generics. In the 3 00:00:10,830 --> 00:00:13,289 simplest definition, generic programming is a 4 00:00:13,290 --> 00:00:15,269 style of computer programming in which 5 00:00:15,270 --> 00:00:17,129 programs are written in terms of to be 6 00:00:17,130 --> 00:00:20,639 specified and later types. We do not specify 7 00:00:20,640 --> 00:00:22,709 the types and keep them generic, and later on, 8 00:00:22,710 --> 00:00:24,833 they're defined based on the data they receive. 9 00:00:25,200 --> 00:00:27,149 All this may seem a bit superficial 10 00:00:27,150 --> 00:00:29,609 for now, but it will start to make sense once 11 00:00:29,610 --> 00:00:32,429 we have some examples. Before jumping into 12 00:00:32,430 --> 00:00:34,739 the concepts and details of generics, I will 13 00:00:34,740 --> 00:00:37,169 start first with a motivating example as to 14 00:00:37,170 --> 00:00:39,659 why we need to use generics. And when they 15 00:00:39,660 --> 00:00:42,089 will be useful for us, please remember that I 16 00:00:42,090 --> 00:00:43,709 will give you a surprise at the end of the 17 00:00:43,710 --> 00:00:45,989 tutorial with regards to generics. For that 18 00:00:45,990 --> 00:00:48,333 you have to stay and wait till the end of the tutorial. 19 00:00:48,334 --> 00:00:50,400 So let's start learning about generics. 20 00:00:51,500 --> 00:00:52,919 Suppose we want to have a function 21 00:00:52,920 --> 00:00:54,929 for computing the square of a given number. 22 00:00:55,409 --> 00:00:58,739 Let me define this function. This is a very 23 00:00:58,740 --> 00:01:00,749 simple implementation of the square function 24 00:01:00,750 --> 00:01:02,729 which will accept an integer, and we'll 25 00:01:02,730 --> 00:01:05,465 compute it square and will return an integer answer. 26 00:01:07,000 --> 00:01:08,699 Let's use this function in the main, 27 00:01:08,700 --> 00:01:11,249 [No Audio] 28 00:01:11,250 --> 00:01:12,869 when we execute, you may note that this 29 00:01:12,870 --> 00:01:15,479 program is working fine. Now, what if I am 30 00:01:15,480 --> 00:01:17,369 interested in finding the square of a float 31 00:01:17,370 --> 00:01:19,709 number. I cannot use the square function 32 00:01:19,710 --> 00:01:22,469 because it uses an i32 type. Of course, I 33 00:01:22,470 --> 00:01:25,109 can write something like number is i32. 34 00:01:25,139 --> 00:01:27,329 But again, it will not compute the exact 35 00:01:27,330 --> 00:01:29,429 square, but rather will truncate the fraction 36 00:01:29,430 --> 00:01:32,069 part, from the number and then it will compute 37 00:01:32,070 --> 00:01:34,889 it square. The only way out will be to write 38 00:01:34,890 --> 00:01:36,569 another function for the square which will 39 00:01:36,570 --> 00:01:38,759 accept a float number and will compute its 40 00:01:38,760 --> 00:01:41,369 respective square. So, let me define another 41 00:01:41,370 --> 00:01:42,779 function for the float type. 42 00:01:42,780 --> 00:01:51,630 [No Audio] 43 00:01:51,631 --> 00:01:54,166 I want to differentiate the square for i32 44 00:01:54,167 --> 00:01:57,120 from that of f32. Therefore, I have to 45 00:01:57,121 --> 00:01:59,866 name it differently. Let us use this function now. 46 00:01:59,867 --> 00:02:06,480 [No Audio] 47 00:02:06,481 --> 00:02:08,370 This was simple function therefore, the code 48 00:02:08,371 --> 00:02:10,620 duplication may not be that much significant. 49 00:02:10,860 --> 00:02:12,810 Consider the case where the function is quite 50 00:02:12,811 --> 00:02:15,000 complex and contains many lines of code and 51 00:02:15,001 --> 00:02:18,990 involves heavy computation. As we will be 52 00:02:18,991 --> 00:02:20,790 writing the code with lots and lots of 53 00:02:20,791 --> 00:02:23,070 duplication in that case, the generics comes 54 00:02:23,071 --> 00:02:25,920 into play here, and it allows us to write code 55 00:02:25,921 --> 00:02:27,533 by minimizing code duplication. 56 00:02:28,900 --> 00:02:31,650 So, let us see the details but first, we will look at 57 00:02:31,651 --> 00:02:33,238 the general syntax. 58 00:02:33,239 --> 00:02:37,258 [No Audio] 59 00:02:37,259 --> 00:02:38,190 To declare a generic 60 00:02:38,191 --> 00:02:40,233 function, I will define the function as usual. 61 00:02:41,200 --> 00:02:42,630 After the function name, I will 62 00:02:42,631 --> 00:02:44,600 mention the input to be of type generic. 63 00:02:44,766 --> 00:02:46,800 To mention this, I will include less than and 64 00:02:46,801 --> 00:02:49,350 greater than symbols and inside that I will 65 00:02:49,351 --> 00:02:51,300 include the name of the generic variable that 66 00:02:51,301 --> 00:02:54,240 I want to use, I can use any name but the 67 00:02:54,241 --> 00:02:57,990 convention is to use the letter T. Next, I 68 00:02:57,991 --> 00:02:59,580 will mention that the input will be of 69 00:02:59,581 --> 00:03:01,500 generic type T by mentioning inside the 70 00:03:01,501 --> 00:03:04,200 parentheses, the type of variable x to be that of T. 71 00:03:06,000 --> 00:03:07,620 For the output of the function, I will 72 00:03:07,621 --> 00:03:09,870 use the same generic type inside the body of 73 00:03:09,871 --> 00:03:12,600 the function I will include the code 74 00:03:12,601 --> 00:03:15,510 for computing the square, let us use it in 75 00:03:15,511 --> 00:03:17,171 the main now. 76 00:03:17,172 --> 00:03:21,133 [No Audio] 77 00:03:21,134 --> 00:03:22,500 I will call it for integer 78 00:03:22,501 --> 00:03:25,020 input as well as for the float input inside 79 00:03:25,021 --> 00:03:26,269 the print statement. 80 00:03:26,270 --> 00:03:30,800 [No Audio] 81 00:03:31,566 --> 00:03:33,270 It seems that the compiler has something to 82 00:03:33,271 --> 00:03:36,450 say to us. It says cannot multiply T by T. 83 00:03:36,600 --> 00:03:38,940 Since T can be anything that is it can be 84 00:03:38,941 --> 00:03:41,970 string or char or integer or float or 85 00:03:41,971 --> 00:03:43,830 unsigned. Therefore, the Rust cannot do the 86 00:03:43,831 --> 00:03:46,500 multiplication in all possible cases. In some 87 00:03:46,501 --> 00:03:48,540 sense, we need to give the compiler a little 88 00:03:48,541 --> 00:03:50,670 bit more information about the possible type 89 00:03:50,671 --> 00:03:52,740 the generic T can be. This additional 90 00:03:52,741 --> 00:03:55,320 information is after the colon, we will 91 00:03:55,321 --> 00:03:57,300 mention a couple of case for the type T which 92 00:03:57,301 --> 00:03:59,310 corresponds to multiplication and copy. 93 00:03:59,311 --> 00:04:04,530 [No Audio] 94 00:04:04,531 --> 00:04:06,810 Okay now what does it mean? It basically 95 00:04:06,811 --> 00:04:08,760 tells the Rust compiler that I am using a 96 00:04:08,761 --> 00:04:11,130 generic which is restricted to any type which 97 00:04:11,131 --> 00:04:13,366 implements the trait of multiplication and copy. 98 00:04:13,733 --> 00:04:15,517 Please note that, we discussed in quite 99 00:04:15,518 --> 00:04:17,766 some detail the difference between copy and move. 100 00:04:18,065 --> 00:04:20,040 The primitive types are copied and not 101 00:04:20,041 --> 00:04:23,100 moved. So this means that, the type T which is 102 00:04:23,101 --> 00:04:26,040 generic, but it does not mean that it can be 103 00:04:26,041 --> 00:04:27,900 anything we are rather restricting it to 104 00:04:27,901 --> 00:04:30,060 types that have the multiplication trait and 105 00:04:30,061 --> 00:04:32,700 the copy trait. The output in front of the 106 00:04:32,701 --> 00:04:34,680 multiplication indicates to it that the 107 00:04:34,681 --> 00:04:36,990 result of the multiplication should result in 108 00:04:36,991 --> 00:04:39,660 a value of type T, that is the generic type. 109 00:04:40,530 --> 00:04:42,630 Once we write the proper restrictions, the 110 00:04:42,631 --> 00:04:45,960 compiler is happy. Please note that the 111 00:04:45,961 --> 00:04:48,750 restrictions depend, on the operations we 112 00:04:48,751 --> 00:04:51,570 intend to perform on generic. For instance, 113 00:04:51,571 --> 00:04:53,460 if we change the multiplication operation to 114 00:04:53,461 --> 00:04:55,470 that of addition, we will need to mention 115 00:04:55,471 --> 00:04:57,750 something else here. The Rust compiler will 116 00:04:57,780 --> 00:05:00,930 always gives us useful hints, if we move our 117 00:05:00,931 --> 00:05:03,266 cursor, in this case you may see relevant hints. 118 00:05:03,500 --> 00:05:04,666 Let us change back. 119 00:05:04,671 --> 00:05:07,900 [No Audio] 120 00:05:07,901 --> 00:05:10,170 We will execute and you may note that, the function is 121 00:05:10,171 --> 00:05:12,450 executed successfully for both the integer 122 00:05:12,451 --> 00:05:14,340 and float values without the need for code 123 00:05:14,341 --> 00:05:19,100 duplication. You may be thinking that, that 124 00:05:19,101 --> 00:05:20,490 it may be very hard to remember 125 00:05:20,491 --> 00:05:22,410 all the restrictions that we may have when 126 00:05:22,411 --> 00:05:25,633 using the generics. Well, this is not that difficult. 127 00:05:25,833 --> 00:05:27,450 If for instance, I forget the 128 00:05:27,451 --> 00:05:29,850 trait of copy, let me delete it from here. 129 00:05:30,180 --> 00:05:32,100 Now, when I execute again 130 00:05:32,101 --> 00:05:35,607 [No Audio] 131 00:05:35,608 --> 00:05:36,480 The Rust compiler 132 00:05:36,481 --> 00:05:38,250 will tell me exactly what is missing by 133 00:05:38,251 --> 00:05:39,800 highlighting it in green text. 134 00:05:39,801 --> 00:05:41,766 [No Audio] 135 00:05:41,767 --> 00:05:44,730 In case if I forget the first one, which is a bit long 136 00:05:44,731 --> 00:05:47,580 too, I will delete it and cargo run again. 137 00:05:47,581 --> 00:05:50,100 [No Audio] 138 00:05:50,101 --> 00:05:52,320 The Rust will give me the exact syntax which 139 00:05:52,321 --> 00:05:54,840 I need to include. Sometimes this list that 140 00:05:54,841 --> 00:05:56,760 we mentioned to restrict the generic may get 141 00:05:56,761 --> 00:05:59,010 too long. For instance, if I add one more 142 00:05:59,011 --> 00:06:00,960 operation inside the function by writing x + x 143 00:06:00,961 --> 00:06:02,900 and execute again. 144 00:06:04,698 --> 00:06:05,340 The Rust will 145 00:06:05,341 --> 00:06:07,740 require one more item here in the list of 146 00:06:07,741 --> 00:06:09,480 four addition which is being shown in the 147 00:06:09,481 --> 00:06:12,966 green text color. Let me copy and add to the list. 148 00:06:12,967 --> 00:06:15,666 [No Audio] 149 00:06:15,667 --> 00:06:16,920 You may note that the list is 150 00:06:16,921 --> 00:06:19,230 getting too big, and it may be difficult to 151 00:06:19,231 --> 00:06:21,630 read down the function definition itself. Let 152 00:06:21,631 --> 00:06:24,266 us provide an alternate syntax for such cases. 153 00:06:25,200 --> 00:06:26,910 We will get all the different traits 154 00:06:26,911 --> 00:06:29,100 information from the list here and will only 155 00:06:29,101 --> 00:06:31,560 keep T. After mentioning the inputs and 156 00:06:31,561 --> 00:06:34,110 outputs. We will move to the next line and 157 00:06:34,111 --> 00:06:36,450 we'll include the where keyword followed by the 158 00:06:36,451 --> 00:06:39,390 complete list. After the list we will start 159 00:06:39,391 --> 00:06:41,730 with the body of the function this syntax is 160 00:06:41,731 --> 00:06:43,666 more readable and more understandable. 161 00:06:43,667 --> 00:06:45,666 [No Audio] 162 00:06:45,667 --> 00:06:47,578 Let us learn how to use structures 163 00:06:47,579 --> 00:06:49,066 in connection with generics. 164 00:06:49,067 --> 00:06:51,684 [No Audio] 165 00:06:51,685 --> 00:06:52,950 Consider a simple structure 166 00:06:52,951 --> 00:06:55,530 which defines a point, a point is defined by 167 00:06:55,531 --> 00:06:57,990 two values one for its location on the x axis 168 00:06:57,991 --> 00:07:00,450 coordinate and another one for specifying its 169 00:07:00,451 --> 00:07:03,270 location on the y axis coordinate. So let us 170 00:07:03,271 --> 00:07:05,383 say 2 fields to the structure definition. 171 00:07:05,384 --> 00:07:11,100 [No Audio] 172 00:07:11,101 --> 00:07:12,690 Let us use this structure in the main to 173 00:07:12,691 --> 00:07:15,870 define some points. I will define point p1 174 00:07:15,871 --> 00:07:18,533 with coordinates having integer values of 5 and 5. 175 00:07:18,534 --> 00:07:20,733 [No Audio] 176 00:07:20,734 --> 00:07:22,440 Now what if I want to create a 177 00:07:22,441 --> 00:07:25,110 point with floating values for its x and y 178 00:07:25,111 --> 00:07:27,750 coordinates. For instance, I will have a 179 00:07:27,751 --> 00:07:30,870 point p2 with coordinates of 1.0 and 4.0. 180 00:07:30,871 --> 00:07:35,340 [No Audio] 181 00:07:35,341 --> 00:07:37,020 The compiler will rightfully 182 00:07:37,021 --> 00:07:40,233 complained in this case, you may note that we 183 00:07:40,234 --> 00:07:42,300 may need some code duplication for 184 00:07:42,301 --> 00:07:44,460 declaring another struct with fields of float 185 00:07:44,461 --> 00:07:47,280 instead of integers. Again, it's anticipated 186 00:07:47,281 --> 00:07:50,220 the generics will help us in this case, we 187 00:07:50,221 --> 00:07:52,140 may define the fields of the structure as 188 00:07:52,141 --> 00:07:55,080 generic instead of some fixed type. I will go 189 00:07:55,081 --> 00:07:56,700 ahead and change the definition of the 190 00:07:56,701 --> 00:07:58,740 structure by first indicating after the name 191 00:07:58,741 --> 00:08:00,930 of the structure, that it will use a generic T 192 00:08:01,860 --> 00:08:03,660 inside the definition of the structure I will 193 00:08:03,661 --> 00:08:05,610 change the type for both the fields to that 194 00:08:05,611 --> 00:08:08,400 of T you may notice the compiler is not 195 00:08:08,401 --> 00:08:12,120 complaining anymore. Okay great so far. Let 196 00:08:12,121 --> 00:08:14,550 me make it a bit more interesting for now, I 197 00:08:14,551 --> 00:08:19,050 will define another point p3 A with x 198 00:08:19,051 --> 00:08:21,570 value being integer and y value being float. 199 00:08:21,571 --> 00:08:28,290 [No Audio] 200 00:08:28,291 --> 00:08:30,000 In this case, now one of the fields is 201 00:08:30,001 --> 00:08:32,520 integer but the other one is that of float, the 202 00:08:32,521 --> 00:08:35,039 compiler is not happy again. This is because 203 00:08:35,040 --> 00:08:37,350 both the fields are of the same generic type. 204 00:08:37,590 --> 00:08:39,720 And once the compiler sees the field of x to 205 00:08:39,721 --> 00:08:41,820 be of integer for a certain instance of the 206 00:08:41,821 --> 00:08:44,340 struct, then it fixes the type of T to that of 207 00:08:44,341 --> 00:08:46,230 integer for that particular instance. 208 00:08:46,500 --> 00:08:49,170 Therefore, it expects the field of y to be of 209 00:08:49,171 --> 00:08:51,600 integer also, for the same instance of the struct. 210 00:08:52,133 --> 00:08:53,520 To allow the two types to be 211 00:08:53,521 --> 00:08:55,800 different, we may introduce another generic 212 00:08:55,801 --> 00:08:58,920 field, let's say the generic of you. So in 213 00:08:58,921 --> 00:09:00,720 the structure definition, I will add another 214 00:09:00,721 --> 00:09:03,330 generic cue. Now I will change the type of 215 00:09:03,360 --> 00:09:04,766 field y to that of u. 216 00:09:06,145 --> 00:09:07,050 You may not now 217 00:09:07,051 --> 00:09:09,900 that the compiler is now happy. Also please 218 00:09:09,901 --> 00:09:12,060 note that in case of first point the Rust 219 00:09:12,061 --> 00:09:14,880 compiler considers both the fields as i32. 220 00:09:14,881 --> 00:09:17,040 In case of p2 the Rust compiler 221 00:09:17,041 --> 00:09:20,166 considers both the fields to be of f64. 222 00:09:20,266 --> 00:09:22,710 In case of p3 however, one of the fields is 223 00:09:22,711 --> 00:09:24,630 considered to be i32 and the other 224 00:09:24,631 --> 00:09:28,170 one is f64. All this is possible due to use 225 00:09:28,171 --> 00:09:30,480 of generics. The point to note is that the 226 00:09:30,481 --> 00:09:32,610 type of the generic will be deduced by the 227 00:09:32,611 --> 00:09:34,770 compiler for each instance of the struct 228 00:09:34,800 --> 00:09:38,310 separately. Okay, now let us look at how we 229 00:09:38,311 --> 00:09:40,230 can implement some functions for the 230 00:09:40,231 --> 00:09:42,360 structure with generics. Suppose I want to 231 00:09:42,361 --> 00:09:44,790 define a function on the point which will 232 00:09:44,791 --> 00:09:47,520 print its x and y fields. This is going to be 233 00:09:47,521 --> 00:09:49,830 very similar to the way we usually define the 234 00:09:49,831 --> 00:09:52,380 implementation block of a struct. So let me 235 00:09:52,381 --> 00:09:55,230 include an implementation block. After the 236 00:09:55,231 --> 00:09:57,300 impl, I will mention the list of generics 237 00:09:57,301 --> 00:10:00,240 inside the less than greater than since there 238 00:10:00,241 --> 00:10:02,550 are two generics in this case, so I will 239 00:10:02,551 --> 00:10:04,620 include their names after the name of the 240 00:10:04,621 --> 00:10:06,810 struct, which is point, I will indicate that 241 00:10:06,840 --> 00:10:08,700 there are two generics with regards to the 242 00:10:08,701 --> 00:10:09,866 point structure. 243 00:10:09,867 --> 00:10:14,549 [No Audio] 244 00:10:14,550 --> 00:10:16,409 Next, I will add a print function and we'll 245 00:10:16,410 --> 00:10:18,629 add a print statement to add for printing the 246 00:10:18,630 --> 00:10:19,901 x and y values. 247 00:10:19,902 --> 00:10:22,471 [No Audio] 248 00:10:22,472 --> 00:10:23,579 You may note that there is 249 00:10:23,580 --> 00:10:26,219 some remaining issues that needs to be 250 00:10:26,220 --> 00:10:29,069 resolved the compiler, the compiler needs 251 00:10:29,070 --> 00:10:31,529 some trait information, let us cargo run this to 252 00:10:31,530 --> 00:10:34,200 see what are the exact traits that I need to include. 253 00:10:34,201 --> 00:10:39,330 [No Audio] 254 00:10:39,331 --> 00:10:41,220 I have the required information in green 255 00:10:41,221 --> 00:10:43,470 color, so I will copy and we'll paste it just 256 00:10:43,471 --> 00:10:46,400 after the impl as indicated in the in our error message. 257 00:10:47,966 --> 00:10:49,500 Please note that as soon as I 258 00:10:49,501 --> 00:10:52,230 include it for generic use the error message 259 00:10:52,231 --> 00:10:54,870 for the self.y disappears. This means 260 00:10:54,871 --> 00:10:56,490 that I need to include the same for the 261 00:10:56,491 --> 00:10:57,700 generic type T. 262 00:10:57,701 --> 00:11:00,599 [No Audio] 263 00:11:00,600 --> 00:11:02,130 Everything is fine. Now, I 264 00:11:02,131 --> 00:11:04,766 will call this function from the main now for point p1. 265 00:11:04,775 --> 00:11:07,200 [No Audio] 266 00:11:07,201 --> 00:11:10,600 Let us execute. It works fine, that's great. 267 00:11:10,900 --> 00:11:12,090 Again, please note that there 268 00:11:12,091 --> 00:11:14,220 is an alternate and more cleaner way of 269 00:11:14,221 --> 00:11:16,350 writing the additional traits by deleting all 270 00:11:16,351 --> 00:11:18,810 the information in this list from here and 271 00:11:18,811 --> 00:11:20,970 paste it separately, with the where 272 00:11:20,971 --> 00:11:23,310 keyword just before the body of the 273 00:11:23,311 --> 00:11:26,160 implementation block. Now as mentioned at the 274 00:11:26,161 --> 00:11:27,540 beginning, I was supposed to give you a 275 00:11:27,541 --> 00:11:30,090 surprise so it's time for that, we have been 276 00:11:30,091 --> 00:11:31,920 using the generic from the very start of the 277 00:11:31,921 --> 00:11:34,410 course. In fact, the vectors basically uses 278 00:11:34,411 --> 00:11:37,080 the generics, the syntax for vectors is vec 279 00:11:37,081 --> 00:11:38,790 and then within the less than greater than 280 00:11:38,820 --> 00:11:41,310 the type information. The type of the vector 281 00:11:41,311 --> 00:11:43,380 is a generic with the type information being 282 00:11:43,381 --> 00:11:46,200 set by us when we declare a vec. This 283 00:11:46,201 --> 00:11:48,810 means that generic is our old friend. Okay 284 00:11:48,811 --> 00:11:51,060 with this, we end this tutorial. In the next 285 00:11:51,061 --> 00:11:53,040 tutorial we will be learning about the Option 286 00:11:53,070 --> 00:11:54,900 enum, which will help us to understand 287 00:11:54,901 --> 00:11:57,180 further the topic of generics and the topic 288 00:11:57,181 --> 00:11:59,370 of enums. That will be fun because we will be 289 00:11:59,371 --> 00:12:01,410 looking at the concept of enums and generics 290 00:12:01,411 --> 00:12:03,690 and action at the same time. Do come back for 291 00:12:03,691 --> 00:12:06,600 learning that and until then, happy Rust programming. 292 00:12:06,601 --> 00:12:12,666 [No Audio]