1 00:00:00,420 --> 00:00:05,910 [Music] 2 00:00:10,160 --> 00:00:15,120 Okay, welcome back everyone. Um, if 3 00:00:12,639 --> 00:00:17,039 there is a seat next to you, would you 4 00:00:15,120 --> 00:00:20,080 mind trying to squish up a little bit so 5 00:00:17,039 --> 00:00:23,920 that we've got room for late comers? Um, 6 00:00:20,080 --> 00:00:27,519 this is not a not the biggest room. Um, 7 00:00:23,920 --> 00:00:30,880 I would like to welcome Evan Cohilus. Uh 8 00:00:27,519 --> 00:00:33,880 Evan's talk is called args amazing or 9 00:00:30,880 --> 00:00:33,880 approaching. 10 00:00:35,680 --> 00:00:41,200 Evan is a serial international speaker 11 00:00:39,200 --> 00:00:43,600 and engineering productivity advocate 12 00:00:41,200 --> 00:00:46,239 who values frictionless simplicity, 13 00:00:43,600 --> 00:00:48,559 taming tech debt, thinking in systems, 14 00:00:46,239 --> 00:00:50,640 and tightening feedback loops. All to 15 00:00:48,559 --> 00:00:54,160 improve the developer experience and 16 00:00:50,640 --> 00:00:56,000 achieve no human errors.com. 17 00:00:54,160 --> 00:00:58,399 When he's not working on his next talk 18 00:00:56,000 --> 00:01:00,000 or project idea, you may catch him as 19 00:00:58,399 --> 00:01:01,840 the assistant director of PyCon 20 00:01:00,000 --> 00:01:03,680 Australia, 21 00:01:01,840 --> 00:01:05,680 tumbling down slopes with a snowboard, 22 00:01:03,680 --> 00:01:07,680 chasing frisbes, or defending subway 23 00:01:05,680 --> 00:01:11,980 cookies. 24 00:01:07,680 --> 00:01:14,960 Please welcome Evan Coilus. 25 00:01:11,980 --> 00:01:18,720 [Applause] 26 00:01:14,960 --> 00:01:20,560 Hello. It's great to be here. Are you 27 00:01:18,720 --> 00:01:20,960 excited? 28 00:01:20,560 --> 00:01:23,680 Yeah. 29 00:01:20,960 --> 00:01:26,400 Yeah. Awesome. Great. because I am too 30 00:01:23,680 --> 00:01:29,439 since I have the utmost adoration for 31 00:01:26,400 --> 00:01:31,520 Python's beautiful function argument and 32 00:01:29,439 --> 00:01:34,720 parameter system. 33 00:01:31,520 --> 00:01:36,960 Just look at it. Isn't it great? 34 00:01:34,720 --> 00:01:38,799 Okay, I'm not I'm not that crazy. I I 35 00:01:36,960 --> 00:01:40,799 think at least. Anyways, we'll just get 36 00:01:38,799 --> 00:01:42,960 the formalities out of the way. Anyone 37 00:01:40,799 --> 00:01:45,439 know what the name of these are called? 38 00:01:42,960 --> 00:01:47,520 Feel free to shout it out. Sorry. 39 00:01:45,439 --> 00:01:49,600 Parameters. Yes, these are called 40 00:01:47,520 --> 00:01:51,520 parameters. They are often mistaken for 41 00:01:49,600 --> 00:01:55,200 arguments and I will mistake them in 42 00:01:51,520 --> 00:01:58,240 this presentation. So don't fault me. 43 00:01:55,200 --> 00:02:01,360 Okay. So what are these? 44 00:01:58,240 --> 00:02:04,000 Yes, these are the arguments. Uh keep 45 00:02:01,360 --> 00:02:05,840 that in mind. All right. So now that 46 00:02:04,000 --> 00:02:07,759 we've got that out of the way, let's go 47 00:02:05,840 --> 00:02:10,319 back to Python's beautiful function 48 00:02:07,759 --> 00:02:13,200 argument system that maybe I am a bit 49 00:02:10,319 --> 00:02:15,040 crazy for. And to show what I'll mean, 50 00:02:13,200 --> 00:02:17,120 I'll start by using a function from 51 00:02:15,040 --> 00:02:19,840 another language. 52 00:02:17,120 --> 00:02:24,239 and I'll change it up to a more concrete 53 00:02:19,840 --> 00:02:26,959 relatable example making rectangles. 54 00:02:24,239 --> 00:02:29,760 I'll also simplify it down to just a 55 00:02:26,959 --> 00:02:32,400 function type signature. 56 00:02:29,760 --> 00:02:34,800 And now this function can be called to 57 00:02:32,400 --> 00:02:37,760 create a basic rectangle of a particular 58 00:02:34,800 --> 00:02:39,680 height and width. 59 00:02:37,760 --> 00:02:41,840 But let's say that a basic rectangle 60 00:02:39,680 --> 00:02:45,760 isn't good enough and we've been asked 61 00:02:41,840 --> 00:02:47,440 to create a rotated one instead. 62 00:02:45,760 --> 00:02:49,920 And to do so, we need to add the 63 00:02:47,440 --> 00:02:53,760 rotation parameter. 64 00:02:49,920 --> 00:02:56,640 Now we can make a rotated rectangle. 65 00:02:53,760 --> 00:02:59,360 But our previous function call now needs 66 00:02:56,640 --> 00:03:02,239 to be updated as it will now error from 67 00:02:59,360 --> 00:03:04,800 not having enough arguments. 68 00:03:02,239 --> 00:03:07,120 And this creates a problem because now 69 00:03:04,800 --> 00:03:09,760 we need to go through and update all of 70 00:03:07,120 --> 00:03:12,000 our previous function calls for any 71 00:03:09,760 --> 00:03:13,760 unrotated rectangle and add that 72 00:03:12,000 --> 00:03:16,239 additional argument to have it default 73 00:03:13,760 --> 00:03:18,800 to zero. 74 00:03:16,239 --> 00:03:21,519 And because this is tedious work that we 75 00:03:18,800 --> 00:03:23,440 as programmers want to avoid in most of 76 00:03:21,519 --> 00:03:27,280 these languages, there are other ways 77 00:03:23,440 --> 00:03:29,920 that a default rotation can be set up. 78 00:03:27,280 --> 00:03:33,200 The most basic way is by creating a new 79 00:03:29,920 --> 00:03:35,040 function with this rotation parameter. 80 00:03:33,200 --> 00:03:38,400 Of course, we don't want to duplicate 81 00:03:35,040 --> 00:03:40,480 code that makes these rectangles. And so 82 00:03:38,400 --> 00:03:43,680 we can update the old function such that 83 00:03:40,480 --> 00:03:46,159 it calls the new function and sets that 84 00:03:43,680 --> 00:03:49,840 new parameter with a default argument 85 00:03:46,159 --> 00:03:52,319 which in our case will be zero. 86 00:03:49,840 --> 00:03:53,920 Now, if we take a step back, we might 87 00:03:52,319 --> 00:03:56,159 start to see how this can get a bit 88 00:03:53,920 --> 00:03:58,319 messy, especially if you have all of 89 00:03:56,159 --> 00:04:00,959 these argument definitions and they a 90 00:03:58,319 --> 00:04:03,680 bunch of defaults and so forth. The good 91 00:04:00,959 --> 00:04:05,760 news is that in some languages, we can 92 00:04:03,680 --> 00:04:08,080 do a bit of cleanup through the use of 93 00:04:05,760 --> 00:04:10,159 function overloading. 94 00:04:08,080 --> 00:04:12,560 With function overloading, we can define 95 00:04:10,159 --> 00:04:15,599 multiple functions with the same name, 96 00:04:12,560 --> 00:04:17,680 but different type signatures. 97 00:04:15,599 --> 00:04:19,759 This removes the need for us to rename 98 00:04:17,680 --> 00:04:22,240 any functions as these programming 99 00:04:19,759 --> 00:04:24,320 languages will determine which functions 100 00:04:22,240 --> 00:04:26,560 to call using the parameter types 101 00:04:24,320 --> 00:04:29,520 instead. 102 00:04:26,560 --> 00:04:31,759 If we looked at the same code in Python, 103 00:04:29,520 --> 00:04:34,080 it would fail. 104 00:04:31,759 --> 00:04:36,560 And this is because in Python, defining 105 00:04:34,080 --> 00:04:38,720 a function with the same name overwrites 106 00:04:36,560 --> 00:04:41,280 that previous definition. It doesn't 107 00:04:38,720 --> 00:04:42,960 work the same way. 108 00:04:41,280 --> 00:04:45,120 And while there are packages like 109 00:04:42,960 --> 00:04:47,600 multiple dispatch that you can use to 110 00:04:45,120 --> 00:04:51,840 replicate function overloading 111 00:04:47,600 --> 00:04:53,600 in general it's a bit problematic and I 112 00:04:51,840 --> 00:04:57,520 wouldn't recommend it for reasons that 113 00:04:53,600 --> 00:05:00,400 will become more apparent later. 114 00:04:57,520 --> 00:05:03,680 So without function overloading how does 115 00:05:00,400 --> 00:05:05,280 Python let us simplify this? 116 00:05:03,680 --> 00:05:07,280 Well, in Python, we have default 117 00:05:05,280 --> 00:05:10,160 arguments, 118 00:05:07,280 --> 00:05:13,720 and these were added back in 1994 for 119 00:05:10,160 --> 00:05:13,720 Python 1.0.2. 120 00:05:13,759 --> 00:05:18,400 And so, what we can do is specify 121 00:05:15,840 --> 00:05:21,680 default arguments using this equal sign 122 00:05:18,400 --> 00:05:23,840 in the parameter definition. 123 00:05:21,680 --> 00:05:26,000 And now, if we only keep a single 124 00:05:23,840 --> 00:05:28,560 definition, we can remove the need for 125 00:05:26,000 --> 00:05:30,960 this function chaining and then remove 126 00:05:28,560 --> 00:05:33,600 the need to pass in zero since it will 127 00:05:30,960 --> 00:05:35,840 use a default instead. 128 00:05:33,600 --> 00:05:37,759 Then we can rename our function back to 129 00:05:35,840 --> 00:05:41,520 rectangle to get our beautiful 130 00:05:37,759 --> 00:05:43,919 definition. Isn't it great? 131 00:05:41,520 --> 00:05:45,919 As a side note, Python is not all 132 00:05:43,919 --> 00:05:48,400 sunshine and rainbows either. And 133 00:05:45,919 --> 00:05:50,000 honestly, I don't think any language is. 134 00:05:48,400 --> 00:05:52,720 And I'll highlight that because of one 135 00:05:50,000 --> 00:05:54,800 detail that can be easily missed. 136 00:05:52,720 --> 00:05:57,039 Let's say, for example, that we wanted 137 00:05:54,800 --> 00:06:00,000 to set a default argument for our 138 00:05:57,039 --> 00:06:02,880 rectangles to contain the metadata based 139 00:06:00,000 --> 00:06:05,199 on how they were created. 140 00:06:02,880 --> 00:06:07,520 And then we added that metadata within 141 00:06:05,199 --> 00:06:09,520 the function. 142 00:06:07,520 --> 00:06:11,520 What you'll find is that instead of the 143 00:06:09,520 --> 00:06:13,840 obvious answer that you'd expect when 144 00:06:11,520 --> 00:06:16,319 printing this metadata, 145 00:06:13,840 --> 00:06:18,000 instead their metadata ends up being the 146 00:06:16,319 --> 00:06:20,000 same. 147 00:06:18,000 --> 00:06:22,240 And this is because in Python, the 148 00:06:20,000 --> 00:06:24,720 values for these default parameters are 149 00:06:22,240 --> 00:06:27,199 created when the function is defined, 150 00:06:24,720 --> 00:06:29,600 not when it's called, 151 00:06:27,199 --> 00:06:31,039 giving this strange outcome where all of 152 00:06:29,600 --> 00:06:34,639 the functions are sharing the same 153 00:06:31,039 --> 00:06:37,919 state, which in this case is 300 and 400 154 00:06:34,639 --> 00:06:39,680 instead of 10 and 20. 155 00:06:37,919 --> 00:06:41,440 So if your functions need mutable 156 00:06:39,680 --> 00:06:44,000 defaults, there is something that you 157 00:06:41,440 --> 00:06:46,160 can do. And the best way to do so is to 158 00:06:44,000 --> 00:06:48,319 default them to none and then set the 159 00:06:46,160 --> 00:06:51,199 mutable that you want if it hasn't been 160 00:06:48,319 --> 00:06:53,120 specified. 161 00:06:51,199 --> 00:06:54,960 Now, if we step away from the 162 00:06:53,120 --> 00:06:57,680 thunderstorms and lightning, which are 163 00:06:54,960 --> 00:07:00,639 very, very frightening, and go back to 164 00:06:57,680 --> 00:07:02,720 our original non-Python example, 165 00:07:00,639 --> 00:07:05,599 how could defaults be done in a language 166 00:07:02,720 --> 00:07:07,759 that doesn't support them? 167 00:07:05,599 --> 00:07:09,680 Well, some of you might be familiar with 168 00:07:07,759 --> 00:07:13,840 a programming construct called a builder 169 00:07:09,680 --> 00:07:16,319 pattern. This is it here. On initiation, 170 00:07:13,840 --> 00:07:19,919 it requires and stores all necessary 171 00:07:16,319 --> 00:07:22,080 data and then allows for adding of any 172 00:07:19,919 --> 00:07:25,840 optional data 173 00:07:22,080 --> 00:07:28,639 before building the final state. 174 00:07:25,840 --> 00:07:31,440 But yet another issue lies with required 175 00:07:28,639 --> 00:07:35,960 arguments that even builders can't fix. 176 00:07:31,440 --> 00:07:35,960 Can anyone spot the error here? 177 00:07:41,840 --> 00:07:48,240 It is a good time for water. 178 00:07:45,599 --> 00:07:50,400 So, 179 00:07:48,240 --> 00:07:52,160 no one noticed that when I defined this 180 00:07:50,400 --> 00:07:55,039 builder, the ordering of height and 181 00:07:52,160 --> 00:07:57,520 width was swapped. 182 00:07:55,039 --> 00:07:59,599 It should be width and height, not 183 00:07:57,520 --> 00:08:01,520 height and width. 184 00:07:59,599 --> 00:08:03,759 And in case you're wondering, I have 185 00:08:01,520 --> 00:08:06,000 seen this in a codebase, so it is 186 00:08:03,759 --> 00:08:08,080 possible. 187 00:08:06,000 --> 00:08:11,520 And going one step further, the same 188 00:08:08,080 --> 00:08:14,080 issue can uh is what can cause um 189 00:08:11,520 --> 00:08:16,240 function overloading to be harmful. For 190 00:08:14,080 --> 00:08:18,479 example, both of these are valid 191 00:08:16,240 --> 00:08:20,319 function definitions. 192 00:08:18,479 --> 00:08:22,560 The only difference being the ordering 193 00:08:20,319 --> 00:08:24,400 of the parameters. 194 00:08:22,560 --> 00:08:26,879 But as soon as we remove the rotation of 195 00:08:24,400 --> 00:08:28,720 the shape, the shape dimensions are now 196 00:08:26,879 --> 00:08:33,319 different because that function falls 197 00:08:28,720 --> 00:08:33,319 back to the other type definition 198 00:08:33,440 --> 00:08:37,039 without having to reference the 199 00:08:34,800 --> 00:08:38,959 signature of the functions. There's no 200 00:08:37,039 --> 00:08:41,919 knowing whether the arguments are set 201 00:08:38,959 --> 00:08:45,680 correctly. 202 00:08:41,919 --> 00:08:47,760 But in 1995, Python 1.3 did the 203 00:08:45,680 --> 00:08:50,800 beautiful thing of adding keyword 204 00:08:47,760 --> 00:08:53,360 arguments. You can see here two words 205 00:08:50,800 --> 00:08:55,760 major change 206 00:08:53,360 --> 00:08:58,240 and this lets us choose what argument we 207 00:08:55,760 --> 00:09:00,880 wish to fill and thus lets us solve 208 00:08:58,240 --> 00:09:03,519 these issues and do away with builders 209 00:09:00,880 --> 00:09:05,360 and function overloading. 210 00:09:03,519 --> 00:09:07,200 Meaning that not only are our functions 211 00:09:05,360 --> 00:09:09,600 self-documenting by having these 212 00:09:07,200 --> 00:09:12,399 constant arguments labeled, which is 213 00:09:09,600 --> 00:09:14,399 amazing, but now our argument ordering 214 00:09:12,399 --> 00:09:16,800 is redundant. 215 00:09:14,399 --> 00:09:19,120 And this might not seem like much, but 216 00:09:16,800 --> 00:09:21,680 this little change of always using 217 00:09:19,120 --> 00:09:24,800 keyword arguments leads to so many 218 00:09:21,680 --> 00:09:26,880 benefits and prevention of errors. 219 00:09:24,800 --> 00:09:28,320 Like for example, if we go back to the 220 00:09:26,880 --> 00:09:29,920 default argument being used for 221 00:09:28,320 --> 00:09:32,959 rotation, 222 00:09:29,920 --> 00:09:36,560 then we could call that function with a 223 00:09:32,959 --> 00:09:39,120 third argument overriding that default. 224 00:09:36,560 --> 00:09:42,240 But once we introduce a new required 225 00:09:39,120 --> 00:09:45,519 positional argument like opacity 226 00:09:42,240 --> 00:09:49,120 where 10, 20, and 45 were previously for 227 00:09:45,519 --> 00:09:50,880 height, width, and rotation, 228 00:09:49,120 --> 00:09:55,600 they're now actually for height, width, 229 00:09:50,880 --> 00:09:57,760 and opacity without us ever knowing. 230 00:09:55,600 --> 00:10:01,120 Naming our arguments easily lets us 231 00:09:57,760 --> 00:10:03,760 prevent this issue, but in addition also 232 00:10:01,120 --> 00:10:05,600 reduces issues with refactoring, 233 00:10:03,760 --> 00:10:09,600 such as in the case where we want to fix 234 00:10:05,600 --> 00:10:11,519 these misordered parameters. 235 00:10:09,600 --> 00:10:13,519 We now don't have to make changes to 236 00:10:11,519 --> 00:10:15,600 reorder those arguments wherever that 237 00:10:13,519 --> 00:10:17,680 function is called. 238 00:10:15,600 --> 00:10:20,160 And if we choose to sort the ordering of 239 00:10:17,680 --> 00:10:23,040 the arguments and parameters, we can 240 00:10:20,160 --> 00:10:25,680 reduce the chance of merge conflicts. 241 00:10:23,040 --> 00:10:28,880 For example, if one commit adds opacity 242 00:10:25,680 --> 00:10:32,000 and rotation and the other adds opacity 243 00:10:28,880 --> 00:10:33,680 and color, when they're combined, 244 00:10:32,000 --> 00:10:36,680 opacity will be in the same place for 245 00:10:33,680 --> 00:10:36,680 both. 246 00:10:36,720 --> 00:10:40,720 And even if you don't care about 247 00:10:38,240 --> 00:10:43,279 refactoring or collaboration, 248 00:10:40,720 --> 00:10:45,680 which I'm sure aren't important, I'd 249 00:10:43,279 --> 00:10:48,480 still recommend using keyword arguments 250 00:10:45,680 --> 00:10:51,279 to reduce human errors. 251 00:10:48,480 --> 00:10:53,440 So, pop quiz. Can anyone spot the error 252 00:10:51,279 --> 00:10:56,000 in this example? 253 00:10:53,440 --> 00:10:59,240 And if you already know, uh, give others 254 00:10:56,000 --> 00:10:59,240 a chance. 255 00:11:08,640 --> 00:11:13,279 It's not easy, right? I'll give you a 256 00:11:10,720 --> 00:11:16,600 hint. It's to do with function arguments 257 00:11:13,279 --> 00:11:16,600 and parameters. 258 00:11:18,720 --> 00:11:23,839 Okay, that's that's not a fair hint. Um, 259 00:11:21,920 --> 00:11:26,720 and that's because there's two problems 260 00:11:23,839 --> 00:11:30,560 here. One is that you can't really know 261 00:11:26,720 --> 00:11:32,000 this without knowing the uh you without 262 00:11:30,560 --> 00:11:34,320 actually knowing the function definition 263 00:11:32,000 --> 00:11:35,760 off by heart. And the other is that 264 00:11:34,320 --> 00:11:37,120 there's all of this complexity around 265 00:11:35,760 --> 00:11:38,560 it, right? You have to be like, oh, is 266 00:11:37,120 --> 00:11:40,480 the regist correct? What if the 267 00:11:38,560 --> 00:11:42,399 replacement function is wrong? What if 268 00:11:40,480 --> 00:11:45,279 the strings are in the wrong order? 269 00:11:42,399 --> 00:11:47,680 Right? And so the the real problem here 270 00:11:45,279 --> 00:11:49,920 is that the way that read.ignore case is 271 00:11:47,680 --> 00:11:51,839 being passed in. 272 00:11:49,920 --> 00:11:54,800 And so if we look at the definition, 273 00:11:51,839 --> 00:11:58,320 you'll see that you know it takes in 274 00:11:54,800 --> 00:12:01,519 pattern replacement string count flags 275 00:11:58,320 --> 00:12:06,000 and read.ignore case is passed in to 276 00:12:01,519 --> 00:12:08,480 where the uh count argument is 277 00:12:06,000 --> 00:12:10,560 not to the flags one. 278 00:12:08,480 --> 00:12:13,200 And so what happens is flag is read in 279 00:12:10,560 --> 00:12:16,399 as a int. And this this flag which is an 280 00:12:13,200 --> 00:12:19,600 enum you know has the value zero to 281 00:12:16,399 --> 00:12:21,279 whatever and in this case it's two. And 282 00:12:19,600 --> 00:12:24,399 so what happens is that the maximum 283 00:12:21,279 --> 00:12:26,320 number of substitutions now becomes two. 284 00:12:24,399 --> 00:12:29,839 And so you might be someone like me 285 00:12:26,320 --> 00:12:32,160 who's like why why on earth is aren't 286 00:12:29,839 --> 00:12:33,839 aren't any substitutions working? What's 287 00:12:32,160 --> 00:12:35,760 wrong with my code? What's wrong with my 288 00:12:33,839 --> 00:12:37,120 replacement function? Like where on 289 00:12:35,760 --> 00:12:39,920 earth is this problem? and then you 290 00:12:37,120 --> 00:12:41,680 finally figure it out. 291 00:12:39,920 --> 00:12:44,160 In fact, so many people have had this 292 00:12:41,680 --> 00:12:46,320 issue that Python has fixed it by 293 00:12:44,160 --> 00:12:48,160 introducing a deprecation warning from 294 00:12:46,320 --> 00:12:51,279 3.13, 295 00:12:48,160 --> 00:12:54,160 noting that the use of counts and flags 296 00:12:51,279 --> 00:12:56,639 as a position argument will be removed 297 00:12:54,160 --> 00:12:58,959 and needs to be used uh as a keyword 298 00:12:56,639 --> 00:13:01,279 instead. 299 00:12:58,959 --> 00:13:03,760 And the way that they will do that is by 300 00:13:01,279 --> 00:13:06,079 putting star as the parameter before 301 00:13:03,760 --> 00:13:09,440 count flags. 302 00:13:06,079 --> 00:13:11,839 So what what is this? What this will do 303 00:13:09,440 --> 00:13:13,920 is it will throw an error when we try to 304 00:13:11,839 --> 00:13:16,160 call the function without naming those 305 00:13:13,920 --> 00:13:18,720 arguments. 306 00:13:16,160 --> 00:13:20,639 And we require that we explicitly 307 00:13:18,720 --> 00:13:23,639 specify the flag with a keyword 308 00:13:20,639 --> 00:13:23,639 argument. 309 00:13:24,079 --> 00:13:30,079 And this feature was added in Python 3.0 310 00:13:26,959 --> 00:13:32,240 which is quite a long time ago. 311 00:13:30,079 --> 00:13:34,240 So if you are convinced by keyword 312 00:13:32,240 --> 00:13:37,920 arguments and I really hope you are by 313 00:13:34,240 --> 00:13:39,920 this point and you want to ensure that 314 00:13:37,920 --> 00:13:42,880 your functions like rectangle are always 315 00:13:39,920 --> 00:13:46,079 called with them. What you can do is 316 00:13:42,880 --> 00:13:47,519 force that by putting star at the at the 317 00:13:46,079 --> 00:13:50,519 first parameter for all of your 318 00:13:47,519 --> 00:13:50,519 functions. 319 00:13:50,560 --> 00:13:53,839 But that would require going through and 320 00:13:52,160 --> 00:13:56,639 updating the arguments to be keyword 321 00:13:53,839 --> 00:13:58,639 arguments. And that can be cumbersome as 322 00:13:56,639 --> 00:14:01,120 you can forget. You can make the code 323 00:13:58,639 --> 00:14:03,920 noisy. Could also require having to go 324 00:14:01,120 --> 00:14:06,240 and do that everywhere. 325 00:14:03,920 --> 00:14:08,160 Not to mention a bunch of redundant 326 00:14:06,240 --> 00:14:10,320 cases where the names of the variables 327 00:14:08,160 --> 00:14:12,560 being passed in are the same as the 328 00:14:10,320 --> 00:14:16,000 parameters. And while this might look 329 00:14:12,560 --> 00:14:18,560 fine, it can get pretty unreadable if 330 00:14:16,000 --> 00:14:21,680 you have parameter names that are much 331 00:14:18,560 --> 00:14:24,160 longer and many more of them 332 00:14:21,680 --> 00:14:29,320 and a bit errorprone. Here's another 333 00:14:24,160 --> 00:14:29,320 question. Can you spot the error here? 334 00:14:31,519 --> 00:14:37,199 Yes. Yeah. If you're going through a 335 00:14:34,800 --> 00:14:39,519 code review very quickly, I bet that 336 00:14:37,199 --> 00:14:42,000 you're going to miss this. 337 00:14:39,519 --> 00:14:44,959 Uh, and in this case, it's the second 338 00:14:42,000 --> 00:14:48,399 argument. If you see it should be y, but 339 00:14:44,959 --> 00:14:50,560 it's actually x. 340 00:14:48,399 --> 00:14:53,040 The good news is that I'm not the only 341 00:14:50,560 --> 00:14:56,480 one who's thought about this. Pep. uh 342 00:14:53,040 --> 00:14:58,720 736 proposes using a trailing equals for 343 00:14:56,480 --> 00:15:01,440 arguments that should take from existing 344 00:14:58,720 --> 00:15:03,760 variable names in the current scope 345 00:15:01,440 --> 00:15:06,880 which is pretty cool. The bad news is 346 00:15:03,760 --> 00:15:10,519 that this was rejected 347 00:15:06,880 --> 00:15:10,519 earlier this year. 348 00:15:10,720 --> 00:15:15,360 Personally though, I feel like llinters 349 00:15:12,880 --> 00:15:17,360 are a cleaner and more pragmatic way not 350 00:15:15,360 --> 00:15:20,880 only to check but also correct this for 351 00:15:17,360 --> 00:15:23,199 us. So I'm not too worried. For example, 352 00:15:20,880 --> 00:15:26,079 we could have a lint rule that enforces 353 00:15:23,199 --> 00:15:28,320 and auto adds a star on all function 354 00:15:26,079 --> 00:15:31,279 definitions. 355 00:15:28,320 --> 00:15:33,519 Or if you don't want to do that, maybe a 356 00:15:31,279 --> 00:15:37,279 rule that enforces function calls to use 357 00:15:33,519 --> 00:15:39,680 keyword arguments wherever possible. 358 00:15:37,279 --> 00:15:42,320 Or if you want the safety without the 359 00:15:39,680 --> 00:15:45,120 redundancy, a rule that for this 360 00:15:42,320 --> 00:15:47,040 parameter and argument warns when a 361 00:15:45,120 --> 00:15:49,120 parameter and argument names don't 362 00:15:47,040 --> 00:15:51,680 match. 363 00:15:49,120 --> 00:15:53,839 And if that's the intention, you can 364 00:15:51,680 --> 00:15:56,639 like rightclick and do the quick fix to 365 00:15:53,839 --> 00:15:59,839 bring clarity with a keyword argument. I 366 00:15:56,639 --> 00:16:02,079 would find this so useful. 367 00:15:59,839 --> 00:16:04,959 So if mitigating human errors excites 368 00:16:02,079 --> 00:16:07,360 you, I'd love to collaborate with you 369 00:16:04,959 --> 00:16:11,279 and see how we can better communicate 370 00:16:07,360 --> 00:16:13,279 this and create more tools. 371 00:16:11,279 --> 00:16:14,800 Or if I've inspired you enough to start 372 00:16:13,279 --> 00:16:16,959 using this paradigm in your code 373 00:16:14,800 --> 00:16:19,120 dayto-day, here are some things that 374 00:16:16,959 --> 00:16:20,720 might be worth noting. 375 00:16:19,120 --> 00:16:22,880 For one, you may notice in your 376 00:16:20,720 --> 00:16:26,240 excitement to use keyword arguments for 377 00:16:22,880 --> 00:16:29,120 all of your function calls that not all 378 00:16:26,240 --> 00:16:30,560 functions are happy with that. 379 00:16:29,120 --> 00:16:33,279 And this is because of another special 380 00:16:30,560 --> 00:16:36,639 parameter slash, 381 00:16:33,279 --> 00:16:38,160 which was added in Python 3.8. When I 382 00:16:36,639 --> 00:16:40,480 found out about this, I was like, whoa, 383 00:16:38,160 --> 00:16:44,000 that's so recent. It was only out of it 384 00:16:40,480 --> 00:16:46,959 only went out of support last year. 385 00:16:44,000 --> 00:16:49,839 And unlike star, which makes all further 386 00:16:46,959 --> 00:16:52,000 um arguments keyword only, slash 387 00:16:49,839 --> 00:16:53,920 prevents all previous parameters from 388 00:16:52,000 --> 00:16:56,160 being passed into using keyword 389 00:16:53,920 --> 00:16:59,120 arguments. 390 00:16:56,160 --> 00:17:00,560 And given the wonders you've seen 391 00:16:59,120 --> 00:17:02,240 with keyword arguments, you'd be like 392 00:17:00,560 --> 00:17:03,680 like why why would you want this? Why is 393 00:17:02,240 --> 00:17:06,000 this helpful? You know, why did they add 394 00:17:03,680 --> 00:17:09,360 this? Well, there are three cases where 395 00:17:06,000 --> 00:17:11,679 I've seen that it is quite useful. The 396 00:17:09,360 --> 00:17:14,079 first is apparent if we had to refactor 397 00:17:11,679 --> 00:17:15,600 our function and change the name of our 398 00:17:14,079 --> 00:17:17,520 parameters. 399 00:17:15,600 --> 00:17:20,400 For example, we may want to change the 400 00:17:17,520 --> 00:17:22,640 specification and be more specific that 401 00:17:20,400 --> 00:17:24,640 rotation should be in degrees and not 402 00:17:22,640 --> 00:17:26,959 radians. 403 00:17:24,640 --> 00:17:29,760 If we updated the name of our parameter, 404 00:17:26,959 --> 00:17:32,720 now any calls that pass in the rotation 405 00:17:29,760 --> 00:17:35,280 argument would now fail if they're used 406 00:17:32,720 --> 00:17:37,520 as keyword arguments. 407 00:17:35,280 --> 00:17:39,919 Thus, by enforcing that a parameter like 408 00:17:37,520 --> 00:17:42,080 rotation can only be passed in as a 409 00:17:39,919 --> 00:17:45,520 positional argument, this refactoring 410 00:17:42,080 --> 00:17:47,280 would no longer be a breaking change 411 00:17:45,520 --> 00:17:48,880 with a trade-off being that our 412 00:17:47,280 --> 00:17:51,039 functions now couldn't use keyword 413 00:17:48,880 --> 00:17:53,120 arguments anymore. So, you know, there's 414 00:17:51,039 --> 00:17:55,679 always a trade-off. 415 00:17:53,120 --> 00:17:58,080 Another case is when we want to keep the 416 00:17:55,679 --> 00:18:00,160 external argument name the same and 417 00:17:58,080 --> 00:18:02,640 change the internal parameter name 418 00:18:00,160 --> 00:18:04,240 within our function. 419 00:18:02,640 --> 00:18:06,160 And we could do that by setting this 420 00:18:04,240 --> 00:18:08,240 parameter to another variable at the top 421 00:18:06,160 --> 00:18:11,280 of the function. 422 00:18:08,240 --> 00:18:13,120 However, this can become messy. Like the 423 00:18:11,280 --> 00:18:15,280 reference to the original parameter 424 00:18:13,120 --> 00:18:18,160 still kept and you have this like header 425 00:18:15,280 --> 00:18:21,760 of all of your functions and 426 00:18:18,160 --> 00:18:23,600 there's always room for error. 427 00:18:21,760 --> 00:18:25,520 And so this is another case where Python 428 00:18:23,600 --> 00:18:27,120 just isn't perfect. 429 00:18:25,520 --> 00:18:29,600 If we take a look at other languages 430 00:18:27,120 --> 00:18:31,600 like Swift, then this concept of naming 431 00:18:29,600 --> 00:18:33,919 parameters different from arguments does 432 00:18:31,600 --> 00:18:36,640 exist. 433 00:18:33,919 --> 00:18:39,760 Like if we convert our previous Python 434 00:18:36,640 --> 00:18:41,760 rectangle example to Swift, then instead 435 00:18:39,760 --> 00:18:43,840 of creating a new variable to rename the 436 00:18:41,760 --> 00:18:46,400 parameter, 437 00:18:43,840 --> 00:18:49,200 an argument label can be used instead 438 00:18:46,400 --> 00:18:50,720 that's internal to the function, 439 00:18:49,200 --> 00:18:52,240 avoiding the need to change the 440 00:18:50,720 --> 00:18:55,760 interface 441 00:18:52,240 --> 00:18:57,360 or create additional variables. 442 00:18:55,760 --> 00:18:59,679 Wouldn't it be awesome if we could do 443 00:18:57,360 --> 00:19:03,400 the same thing in Python? The code would 444 00:18:59,679 --> 00:19:03,400 be nice and more readable. 445 00:19:03,600 --> 00:19:08,480 It's worth noting that this feature also 446 00:19:06,160 --> 00:19:10,400 exists in JavaScript. 447 00:19:08,480 --> 00:19:12,880 It looks like this, which is quite 448 00:19:10,400 --> 00:19:14,960 similar, but for those of you unfamiliar 449 00:19:12,880 --> 00:19:17,679 with JavaScript, the way it works is 450 00:19:14,960 --> 00:19:20,240 actually quite different. And the secret 451 00:19:17,679 --> 00:19:22,400 is in these braces. 452 00:19:20,240 --> 00:19:25,679 And because the braces really define an 453 00:19:22,400 --> 00:19:27,600 object like a Python dictionary, what's 454 00:19:25,679 --> 00:19:29,600 really happening here is there's only 455 00:19:27,600 --> 00:19:32,760 really one argument being passed into 456 00:19:29,600 --> 00:19:32,760 this function. 457 00:19:33,039 --> 00:19:36,799 And so the values of the object being 458 00:19:34,880 --> 00:19:39,360 passed in 459 00:19:36,799 --> 00:19:41,520 are being destructed into the variables 460 00:19:39,360 --> 00:19:43,919 width and height 461 00:19:41,520 --> 00:19:46,960 with rotation being reassigned to a 462 00:19:43,919 --> 00:19:49,039 different name 463 00:19:46,960 --> 00:19:52,799 which in effect is like assigning the 464 00:19:49,039 --> 00:19:57,280 variables from an object individually. 465 00:19:52,799 --> 00:20:00,000 Okay. So why am I explaining all this? 466 00:19:57,280 --> 00:20:03,039 This is because in the year 2000 Python 467 00:20:00,000 --> 00:20:05,360 1.6 six added support for unpacking into 468 00:20:03,039 --> 00:20:07,360 function calls, 469 00:20:05,360 --> 00:20:10,240 letting us do what JavaScript does with 470 00:20:07,360 --> 00:20:12,720 dictionaries too. 471 00:20:10,240 --> 00:20:14,880 And by using the double star operator 472 00:20:12,720 --> 00:20:17,840 within a function call, Python will 473 00:20:14,880 --> 00:20:21,200 unpack the keys of the dictionary as the 474 00:20:17,840 --> 00:20:23,280 keywords um the keys of the dictionary 475 00:20:21,200 --> 00:20:25,200 as the keywords and the values as the 476 00:20:23,280 --> 00:20:27,200 arguments. 477 00:20:25,200 --> 00:20:29,679 And this might make you wonder what 478 00:20:27,200 --> 00:20:32,320 happens if extra properties are passed 479 00:20:29,679 --> 00:20:34,400 into these function calls. 480 00:20:32,320 --> 00:20:37,840 Well, I'm sorry to disappoint you. In 481 00:20:34,400 --> 00:20:39,760 JavaScript, the answer is nothing. Uh 482 00:20:37,840 --> 00:20:41,840 they don't get unpacked and thus they're 483 00:20:39,760 --> 00:20:43,840 ignored. 484 00:20:41,840 --> 00:20:47,039 But there is a way to keep them and that 485 00:20:43,840 --> 00:20:49,600 is by using the ellipsus dot dot dot uh 486 00:20:47,039 --> 00:20:51,760 rest property. 487 00:20:49,600 --> 00:20:53,679 And this allows us to save the remaining 488 00:20:51,760 --> 00:20:57,000 properties for whatever they may be 489 00:20:53,679 --> 00:20:57,000 needed for. 490 00:20:57,120 --> 00:21:01,600 But if this is how JavaScript name 491 00:20:58,880 --> 00:21:03,919 parameters work, what happens in Python 492 00:21:01,600 --> 00:21:07,440 if we pass in extra keyword arguments 493 00:21:03,919 --> 00:21:09,440 into a Python function? 494 00:21:07,440 --> 00:21:12,640 Well, unlike JavaScript, we'll get an 495 00:21:09,440 --> 00:21:15,120 error telling us off that we passed in 496 00:21:12,640 --> 00:21:16,799 an unexpected keyword argument, which 497 00:21:15,120 --> 00:21:20,159 you could argue is pretty good default 498 00:21:16,799 --> 00:21:22,960 behavior. And I say default here because 499 00:21:20,159 --> 00:21:25,600 you can also specify a way to keep these 500 00:21:22,960 --> 00:21:27,840 leftover arguments. 501 00:21:25,600 --> 00:21:30,640 And that is by using our good friend 502 00:21:27,840 --> 00:21:32,720 double star again adding it to a rest 503 00:21:30,640 --> 00:21:34,880 parameter. 504 00:21:32,720 --> 00:21:37,600 And this captures any extra keyword 505 00:21:34,880 --> 00:21:40,400 arguments into a dictionary. 506 00:21:37,600 --> 00:21:42,240 As a side note, similar to JavaScript, 507 00:21:40,400 --> 00:21:45,039 this parameter doesn't have to be called 508 00:21:42,240 --> 00:21:48,000 rest either. And the general convention 509 00:21:45,039 --> 00:21:50,480 in Python is to use quags for keyword 510 00:21:48,000 --> 00:21:55,679 arguments, 511 00:21:50,480 --> 00:21:58,400 which was also added back in Python 1.3. 512 00:21:55,679 --> 00:22:00,159 And unlike JavaScript, Python doesn't 513 00:21:58,400 --> 00:22:03,679 currently have a way to unpack 514 00:22:00,159 --> 00:22:06,159 parameters within function definitions. 515 00:22:03,679 --> 00:22:08,240 But fun fact, it did used to in Python, 516 00:22:06,159 --> 00:22:10,159 too. 517 00:22:08,240 --> 00:22:13,120 Well, it only really worked if you 518 00:22:10,159 --> 00:22:16,480 passed in a tpple and defined the 519 00:22:13,120 --> 00:22:18,400 parameters with tpples as well and then 520 00:22:16,480 --> 00:22:21,120 they were unpacked for use within the 521 00:22:18,400 --> 00:22:23,039 function. And this was kind of removed 522 00:22:21,120 --> 00:22:25,520 because it wasn't getting much use. It 523 00:22:23,039 --> 00:22:27,600 was more confusing. But maybe we'll come 524 00:22:25,520 --> 00:22:29,360 back to Python 3 differently after a 525 00:22:27,600 --> 00:22:32,240 pep. 526 00:22:29,360 --> 00:22:34,080 Anyways, where were we? 527 00:22:32,240 --> 00:22:37,600 A question you might have about double 528 00:22:34,080 --> 00:22:40,000 star is what happens if arguments are 529 00:22:37,600 --> 00:22:42,320 provided in the function with the double 530 00:22:40,000 --> 00:22:44,559 star. 531 00:22:42,320 --> 00:22:46,720 Well, Python will nicely tell us that 532 00:22:44,559 --> 00:22:48,640 we've made a mistake 533 00:22:46,720 --> 00:22:52,799 and we'll get the same error if they're 534 00:22:48,640 --> 00:22:54,559 passed in as positionals instead. 535 00:22:52,799 --> 00:22:56,640 And if you did want to make it such that 536 00:22:54,559 --> 00:22:59,919 this was okay, there is one thing that 537 00:22:56,640 --> 00:23:01,760 you can do and this is the last of the 538 00:22:59,919 --> 00:23:04,640 three cases that I mentioned earlier. if 539 00:23:01,760 --> 00:23:08,799 if you noticed as another use of slash 540 00:23:04,640 --> 00:23:11,520 to enforce these positional arguments 541 00:23:08,799 --> 00:23:15,679 making it such that those extra keyword 542 00:23:11,520 --> 00:23:17,360 arguments are forced into quags. 543 00:23:15,679 --> 00:23:20,559 And now you might have noticed that 544 00:23:17,360 --> 00:23:22,320 quags is is pretty cool since it lets us 545 00:23:20,559 --> 00:23:24,159 pass in an arbitrary number of 546 00:23:22,320 --> 00:23:26,080 arguments. 547 00:23:24,159 --> 00:23:28,960 But there are also cases where we can't 548 00:23:26,080 --> 00:23:30,799 define a keyword for every argument. For 549 00:23:28,960 --> 00:23:33,120 example, if we wanted to sum a list of 550 00:23:30,799 --> 00:23:36,240 numbers. 551 00:23:33,120 --> 00:23:40,799 Thankfully, back in 1992, this was added 552 00:23:36,240 --> 00:23:43,039 as part of Python 0.9. 553 00:23:40,799 --> 00:23:45,280 6. 554 00:23:43,039 --> 00:23:47,760 And so, we can use star args, which is 555 00:23:45,280 --> 00:23:49,840 like quags, but for positional 556 00:23:47,760 --> 00:23:52,400 arguments. 557 00:23:49,840 --> 00:23:54,400 Args then appears as a variable that 558 00:23:52,400 --> 00:23:57,120 holds a tpple of all of these extra 559 00:23:54,400 --> 00:24:00,159 arguments that were passed in. And it's 560 00:23:57,120 --> 00:24:01,919 worth noting by the nature of star args 561 00:24:00,159 --> 00:24:04,960 capturing all of these additional 562 00:24:01,919 --> 00:24:09,440 positional arguments that any further 563 00:24:04,960 --> 00:24:12,880 parameters must be keyword only. 564 00:24:09,440 --> 00:24:16,159 So if a new parameter is added after it 565 00:24:12,880 --> 00:24:20,000 and the function is run as before, we'll 566 00:24:16,159 --> 00:24:22,240 get a missing keyword argument error 567 00:24:20,000 --> 00:24:24,400 unless that argument is passed in as a 568 00:24:22,240 --> 00:24:27,200 keyword. 569 00:24:24,400 --> 00:24:28,720 And if an extra argument is passed in, 570 00:24:27,200 --> 00:24:32,400 then we'll get an error from an 571 00:24:28,720 --> 00:24:35,440 unexpected keyword argument. 572 00:24:32,400 --> 00:24:39,799 What if we wanted to be sure that we 573 00:24:35,440 --> 00:24:39,799 could pass in all arguments? 574 00:24:40,159 --> 00:24:44,640 Then we could end the definition with 575 00:24:42,320 --> 00:24:47,200 star double star quags so that our 576 00:24:44,640 --> 00:24:49,360 function captures both. 577 00:24:47,200 --> 00:24:53,600 And this would let us pass in all extra 578 00:24:49,360 --> 00:24:55,679 arguments down to other functions. 579 00:24:53,600 --> 00:24:58,559 And similar to double star that allows 580 00:24:55,679 --> 00:25:01,200 for unpacking within a function call, we 581 00:24:58,559 --> 00:25:03,840 can also do the same thing with star to 582 00:25:01,200 --> 00:25:06,799 unpack into functions with variable 583 00:25:03,840 --> 00:25:09,799 arguments to respect the shapes function 584 00:25:06,799 --> 00:25:09,799 definition. 585 00:25:09,840 --> 00:25:15,120 But are arbitrary keyword opposition 586 00:25:12,400 --> 00:25:16,640 arguments a good idea? This is a good 587 00:25:15,120 --> 00:25:18,640 question. 588 00:25:16,640 --> 00:25:22,559 For that, we can look at the design of 589 00:25:18,640 --> 00:25:25,440 safer, newer languages like Rust. 590 00:25:22,559 --> 00:25:28,159 And I'm no expert in Rust. And to my 591 00:25:25,440 --> 00:25:30,960 best understanding, Rust doesn't support 592 00:25:28,159 --> 00:25:33,039 variable function arguments. Not only is 593 00:25:30,960 --> 00:25:35,279 it hard for the type checker, but it's 594 00:25:33,039 --> 00:25:37,039 also hard for the reader. And so if you 595 00:25:35,279 --> 00:25:39,039 do want this complexity, there are two 596 00:25:37,039 --> 00:25:40,559 things you can do. You can pass in 597 00:25:39,039 --> 00:25:42,320 lists, 598 00:25:40,559 --> 00:25:45,200 uh, which doesn't cause these variable 599 00:25:42,320 --> 00:25:47,600 type signatures, or macros, which 600 00:25:45,200 --> 00:25:49,360 essentially pass that complexity onto 601 00:25:47,600 --> 00:25:52,400 the writer to figure out what exactly 602 00:25:49,360 --> 00:25:54,720 you want to do. 603 00:25:52,400 --> 00:25:57,039 And this complexity is quite evident in 604 00:25:54,720 --> 00:25:59,679 Python since they can make functions 605 00:25:57,039 --> 00:26:02,799 difficult to understand how they should 606 00:25:59,679 --> 00:26:05,200 be used given there's no need for types. 607 00:26:02,799 --> 00:26:07,279 For example, like what can be what 608 00:26:05,200 --> 00:26:08,720 arguments can be passed into here. I'm 609 00:26:07,279 --> 00:26:11,520 sure you've read code like this and 610 00:26:08,720 --> 00:26:14,720 you're like I'm just going to try and 611 00:26:11,520 --> 00:26:16,480 find out, right? 612 00:26:14,720 --> 00:26:18,799 Even if they are typed in their most 613 00:26:16,480 --> 00:26:21,200 simple form, it requires the value to be 614 00:26:18,799 --> 00:26:23,760 of the same type, which you could say 615 00:26:21,200 --> 00:26:26,080 for the case of args is fine because if 616 00:26:23,760 --> 00:26:28,400 they needed to be typed differently, 617 00:26:26,080 --> 00:26:32,400 then in most cases the definition should 618 00:26:28,400 --> 00:26:35,200 be updated with those parameter types. 619 00:26:32,400 --> 00:26:38,960 and for typing keyword arguments. Only 620 00:26:35,200 --> 00:26:41,760 from Python 3.11 were additions added as 621 00:26:38,960 --> 00:26:43,840 support to help specify that keywords 622 00:26:41,760 --> 00:26:46,159 could be called and what their types 623 00:26:43,840 --> 00:26:49,039 could be. 624 00:26:46,159 --> 00:26:50,559 And so to recap, this is Python's 625 00:26:49,039 --> 00:26:53,279 beautiful function argument and 626 00:26:50,559 --> 00:26:55,279 parameter system. The slash special 627 00:26:53,279 --> 00:26:58,559 parameter marks that the previous 628 00:26:55,279 --> 00:27:00,480 parameters are positional only. There's 629 00:26:58,559 --> 00:27:03,760 also the standard parameter that can be 630 00:27:00,480 --> 00:27:06,320 positional or keyword and can also be 631 00:27:03,760 --> 00:27:09,120 set with a default 632 00:27:06,320 --> 00:27:11,120 as can positional only if they and all 633 00:27:09,120 --> 00:27:13,679 other positional arguments are also 634 00:27:11,120 --> 00:27:15,760 given defaults. 635 00:27:13,679 --> 00:27:18,880 Star captures an arbitrary number of 636 00:27:15,760 --> 00:27:22,320 positional arguments and also indicates 637 00:27:18,880 --> 00:27:24,880 that further parameters are keyword only 638 00:27:22,320 --> 00:27:27,440 such as this keyword argument or this 639 00:27:24,880 --> 00:27:29,840 one with a default. 640 00:27:27,440 --> 00:27:32,799 And star can also be used alone as a 641 00:27:29,840 --> 00:27:35,039 special parameter to do the same. And 642 00:27:32,799 --> 00:27:38,320 finally, double star to handle those 643 00:27:35,039 --> 00:27:41,279 arbitrary keyword arguments. 644 00:27:38,320 --> 00:27:43,520 And so while we can argue that Python's 645 00:27:41,279 --> 00:27:46,720 function argument system is both 646 00:27:43,520 --> 00:27:49,279 approaching and amazing, at the least 647 00:27:46,720 --> 00:27:50,880 it's forever changing. 648 00:27:49,279 --> 00:27:52,400 If you're after the resources for this 649 00:27:50,880 --> 00:27:53,919 talk, I've seen everyone take some 650 00:27:52,400 --> 00:27:57,840 photos. You can find them in these 651 00:27:53,919 --> 00:28:00,399 links. Um or if you're after me, you can 652 00:27:57,840 --> 00:28:04,080 collaborate with me online on nohuman 653 00:28:00,399 --> 00:28:05,440 errors.com or find me at ecohillos or 654 00:28:04,080 --> 00:28:08,159 here if you have any questions or 655 00:28:05,440 --> 00:28:10,240 feedback. Thank you to my friends, 656 00:28:08,159 --> 00:28:12,240 family, and the open source community, 657 00:28:10,240 --> 00:28:15,240 as well as to you for listening. Thank 658 00:28:12,240 --> 00:28:15,240 you. 659 00:28:18,580 --> 00:28:22,080 [Applause] 660 00:28:20,080 --> 00:28:22,480 Thank you very much, Evan. Here is your 661 00:28:22,080 --> 00:28:24,559 mug. 662 00:28:22,480 --> 00:28:27,360 Thank you so much. It's been a pleasure. 663 00:28:24,559 --> 00:28:28,880 Um, we've got about one or two minutes 664 00:28:27,360 --> 00:28:31,279 for questions if we've got a couple of 665 00:28:28,880 --> 00:28:34,520 quick ones. We've got one right up the 666 00:28:31,279 --> 00:28:34,520 back here. 667 00:28:40,799 --> 00:28:45,919 Um, what do you think about using new 668 00:28:43,200 --> 00:28:48,399 type to type things like height and 669 00:28:45,919 --> 00:28:50,880 width? So you have like a width new type 670 00:28:48,399 --> 00:28:55,200 and a height new type instead of just 671 00:28:50,880 --> 00:28:57,600 using ins to improve type safety. 672 00:28:55,200 --> 00:29:01,279 That's a good question. That's a complex 673 00:28:57,600 --> 00:29:03,360 question. Uh, let's talk after this. 674 00:29:01,279 --> 00:29:06,000 All right. Um well I know that rough 675 00:29:03,360 --> 00:29:08,480 does have some rules for detecting 676 00:29:06,000 --> 00:29:10,880 positional boolean parameters which 677 00:29:08,480 --> 00:29:12,960 definitely ties into this talk but not 678 00:29:10,880 --> 00:29:15,919 for other types of parameters. 679 00:29:12,960 --> 00:29:20,320 Yes, a lot of these um rough does have 680 00:29:15,919 --> 00:29:23,919 some uh but majority of these rely on 681 00:29:20,320 --> 00:29:25,919 the lint knowing what the uh definition 682 00:29:23,919 --> 00:29:28,080 looks like and rough doesn't support 683 00:29:25,919 --> 00:29:31,200 that yet. It's on their road map, but it 684 00:29:28,080 --> 00:29:34,559 essentially requires like um integrating 685 00:29:31,200 --> 00:29:36,080 in TY and all of that. Um so as soon as 686 00:29:34,559 --> 00:29:38,640 they do that, that's the first thing I'm 687 00:29:36,080 --> 00:29:43,279 going to do. But until then, you can use 688 00:29:38,640 --> 00:29:45,360 llinters like uh pilint, I think, which 689 00:29:43,279 --> 00:29:47,039 has access to that. But then you also 690 00:29:45,360 --> 00:29:52,880 have the problem that it's a bit slower. 691 00:29:47,039 --> 00:29:54,080 So um yeah. Cool. Thank you again, Evan. 692 00:29:52,880 --> 00:29:54,320 Another round of applause for Evan, 693 00:29:54,080 --> 00:29:57,600 please. 694 00:29:54,320 --> 00:29:57,600 Thank you so much.