1 00:00:00,000 --> 00:00:06,900 [No Audio] 2 00:00:06,901 --> 00:00:09,366 This tutorial is about a special concept in 3 00:00:09,367 --> 00:00:12,066 Rust called trait bounds. We covered the 4 00:00:12,067 --> 00:00:14,400 trait in Section 5 of the course in the 5 00:00:14,401 --> 00:00:16,866 context of structures, let us recall that. 6 00:00:16,867 --> 00:00:19,800 A trait defines a particular functionality data 7 00:00:19,801 --> 00:00:22,633 type has, which it can share with other types. 8 00:00:23,033 --> 00:00:25,266 We can use traits to define shared behavior 9 00:00:25,267 --> 00:00:27,800 in an abstract way. For instance, we can have 10 00:00:27,801 --> 00:00:30,033 a trait of general info for the Student and 11 00:00:30,034 --> 00:00:31,800 Person types, giving us some general 12 00:00:31,801 --> 00:00:34,800 information about the respective types. The 13 00:00:34,801 --> 00:00:37,533 trait bounds are used to specify and restrict 14 00:00:37,534 --> 00:00:40,066 the generic types to only those types, which 15 00:00:40,067 --> 00:00:42,466 has certain behavior, or more specifically has 16 00:00:42,467 --> 00:00:45,066 certain traits, that are implemented for that 17 00:00:45,067 --> 00:00:47,733 specific type. Let's look at an example which 18 00:00:47,734 --> 00:00:50,033 will make things more obvious and easy to 19 00:00:50,034 --> 00:00:52,500 comprehend. Consider a simple program which 20 00:00:52,501 --> 00:00:55,066 uses a double function to compute a quadruple 21 00:00:55,067 --> 00:00:57,000 of a given number, by calling the double 22 00:00:57,001 --> 00:00:59,800 function twice, Let us implement the double 23 00:00:59,801 --> 00:01:02,433 function inside a trait called Double. 24 00:01:02,434 --> 00:01:14,066 [No Audio] 25 00:01:14,067 --> 00:01:16,066 The trait called Double containing a single 26 00:01:16,067 --> 00:01:18,233 function of double, which returns the double 27 00:01:18,234 --> 00:01:20,666 of the given type, let us implement this 28 00:01:20,667 --> 00:01:22,200 trait for an i32. 29 00:01:22,201 --> 00:01:28,333 [No Audio] 30 00:01:28,334 --> 00:01:30,466 This was simple. Let us now include the 31 00:01:30,467 --> 00:01:33,233 quadruple function now, which will call the 32 00:01:33,266 --> 00:01:34,733 double function twice. 33 00:01:34,734 --> 00:01:42,100 [No Audio] 34 00:01:42,101 --> 00:01:44,033 Let us call the quadruple function from the 35 00:01:44,034 --> 00:01:45,900 main now inside the print statement. 36 00:01:45,901 --> 00:01:52,433 [No Audio] 37 00:01:52,434 --> 00:01:54,900 This however, will only work for an i32 38 00:01:54,901 --> 00:01:59,033 type. What if I want the same for an i64 type? 39 00:01:59,034 --> 00:02:00,900 I will implement the same Double for an 40 00:02:00,901 --> 00:02:04,066 i64 type also, so let me do it. 41 00:02:04,067 --> 00:02:11,533 [No Audio] 42 00:02:11,534 --> 00:02:14,100 So, now we have the Double for i64, but the 43 00:02:14,101 --> 00:02:17,100 function quadruple is only for i32, this 44 00:02:17,101 --> 00:02:19,200 means that, I will need to define another 45 00:02:19,201 --> 00:02:22,533 function for i64 also, it will be 46 00:02:22,534 --> 00:02:25,033 pretty pedestrian to approach it like this. 47 00:02:25,034 --> 00:02:27,900 Luckily, we have generics in Rust, which we 48 00:02:27,901 --> 00:02:30,433 can introduce instead, which will relax the 49 00:02:30,434 --> 00:02:32,600 condition on the inputs to be of some 50 00:02:32,601 --> 00:02:34,600 specific type only. Let us 51 00:02:34,633 --> 00:02:37,000 introduce the generic of T in this case. 52 00:02:37,001 --> 00:02:39,666 [No Audio] 53 00:02:39,667 --> 00:02:41,066 Let us execute this now. 54 00:02:41,067 --> 00:02:46,933 [No Audio] 55 00:02:46,934 --> 00:02:49,200 It appears that the compiler does not like 56 00:02:49,201 --> 00:02:52,700 this at all. It says, items for trait can only 57 00:02:52,701 --> 00:02:55,800 be used if the type parameter is bounded by 58 00:02:55,801 --> 00:02:59,400 the trait. Let us look at it in some detail. 59 00:03:00,300 --> 00:03:02,400 First, the compiler notice that the quadruple 60 00:03:02,401 --> 00:03:06,133 works on any type T, that's fine. This means 61 00:03:06,134 --> 00:03:08,700 that, whoever calls this function gets to 62 00:03:08,701 --> 00:03:12,166 decide what T is, that is also fine. However, 63 00:03:12,167 --> 00:03:14,766 the compiler has no way of knowing if t is 64 00:03:14,767 --> 00:03:17,100 going to have a method called Double on it. 65 00:03:17,400 --> 00:03:20,900 If it happens to be an i32 or i64, then it 66 00:03:20,901 --> 00:03:24,533 will have it, but if it is i16 or i8, then 67 00:03:24,534 --> 00:03:26,933 it will not have it. Since there is no 68 00:03:26,934 --> 00:03:28,833 restriction on the type of T, therefore the 69 00:03:28,834 --> 00:03:31,800 compiler has no way of assuring that T will 70 00:03:31,801 --> 00:03:34,300 always be going to have a method called 71 00:03:34,301 --> 00:03:37,500 double on it. The compiler is however smart 72 00:03:37,501 --> 00:03:39,300 enough to notice that there is a trait called 73 00:03:39,301 --> 00:03:42,233 double, which provides a double method. Maybe 74 00:03:42,266 --> 00:03:45,866 that's what we want it to use. It therefore 75 00:03:45,867 --> 00:03:47,433 gives a nice suggestions that you need to 76 00:03:47,434 --> 00:03:49,933 introduce a trait bound. Let me add a trait 77 00:03:49,934 --> 00:03:51,466 bound to the parameter T. 78 00:03:51,467 --> 00:03:55,900 [No Audio] 79 00:03:55,901 --> 00:03:57,866 The trait bounds introduces a 80 00:03:57,867 --> 00:04:00,100 restriction on the types that a 81 00:04:00,101 --> 00:04:02,900 caller can use when using type parameters. 82 00:04:02,901 --> 00:04:06,900 Uptil now, we have seen unbounded type parameters, 83 00:04:06,901 --> 00:04:10,233 which means, you can use whatever, whatever 84 00:04:10,234 --> 00:04:13,366 type you want. However, with quadruple it is 85 00:04:13,367 --> 00:04:17,366 using an item from a trait of Double. Uptil 86 00:04:17,367 --> 00:04:20,000 now, we have seen unbounded type parameters, 87 00:04:20,001 --> 00:04:22,566 which means, you can use whatever type you 88 00:04:22,567 --> 00:04:25,933 want. However with quadruple, it is using an 89 00:04:25,934 --> 00:04:29,233 item from a trait of double. By item we mean, a 90 00:04:29,234 --> 00:04:32,100 function in this case, which is only defined 91 00:04:32,101 --> 00:04:33,900 for some specific type, and therefore we 92 00:04:33,901 --> 00:04:37,200 cannot be so accepting in this case. Instead, 93 00:04:37,201 --> 00:04:40,833 we would we want to say, okay, you can give me 94 00:04:40,866 --> 00:04:43,200 lots of different types for the, for the 95 00:04:43,201 --> 00:04:46,133 generic T, but just make sure they implement 96 00:04:46,134 --> 00:04:48,433 the Double trait. In some sense, we are 97 00:04:48,434 --> 00:04:51,033 telling the compiler that, T can be any type 98 00:04:51,300 --> 00:04:53,466 which has the behavior or property of Double 99 00:04:53,467 --> 00:04:56,366 implemented for it. If it does not implement 100 00:04:56,367 --> 00:04:59,100 Double, then the compiler, then the compiler 101 00:04:59,101 --> 00:05:01,366 will run into issues of exactly determining 102 00:05:01,367 --> 00:05:03,966 the type for the parameter T. The programmer 103 00:05:03,967 --> 00:05:06,533 now has the responsibility of when calling 104 00:05:06,534 --> 00:05:08,766 the quadruple function, to make sure that the 105 00:05:08,767 --> 00:05:11,166 type we are using has an implementation for 106 00:05:11,167 --> 00:05:14,266 Double. That is it for this tutorial. I hope 107 00:05:14,267 --> 00:05:16,200 you would have enjoyed this. Do come back 108 00:05:16,201 --> 00:05:19,300 again for more, and until then enjoy Rust programming. 109 00:05:19,301 --> 00:05:23,366 [No Audio]