1 00:00:00,450 --> 00:00:03,420 We seemingly solve the problem of building a function that 2 00:00:03,420 --> 00:00:05,900 accepts a closure they can throw an error. 3 00:00:05,900 --> 00:00:07,956 It is a hidden catch however. 4 00:00:07,956 --> 00:00:11,422 So, right after this code, let's use our apply function again. 5 00:00:11,422 --> 00:00:15,560 Say 10.apply(12). 6 00:00:15,560 --> 00:00:19,473 And here we'll say \$0 + \$1. 7 00:00:19,473 --> 00:00:23,185 Here I'm trying to add 10 to 12. 8 00:00:23,185 --> 00:00:27,814 There is absolutely no way, no possible way, that this can go wrong. 9 00:00:27,814 --> 00:00:32,220 But it's not evident here, but as you can see from my console log, 10 00:00:32,220 --> 00:00:37,276 the compiler wants us to use the try statement and handle potential errors. 11 00:00:37,276 --> 00:00:41,528 Because we've marked the outer function apply as a throwing one. 12 00:00:41,528 --> 00:00:46,580 And that's annoying, it says here, call can throw but is not marked with try. 13 00:00:46,580 --> 00:00:50,220 That means that even if there's no chance that there's going to be an error, 14 00:00:50,220 --> 00:00:54,910 we need to go through do, try, and catch because of the way we've written our code. 15 00:00:54,910 --> 00:00:57,780 And thankfully, that's not how it's done. 16 00:00:57,780 --> 00:01:01,050 So, instead of the throws keyword on the outer function, 17 00:01:01,050 --> 00:01:04,320 so on apply we have this throws right here. 18 00:01:04,320 --> 00:01:07,230 We're gonna change this to say rethrows. 19 00:01:07,230 --> 00:01:09,180 And now, everything magically works, and 20 00:01:09,180 --> 00:01:12,270 you'll see here that this function has been called. 21 00:01:12,270 --> 00:01:13,370 What just happened? 22 00:01:13,370 --> 00:01:17,850 Reathers is a pretty special keyword that you can use in conjunction 23 00:01:17,850 --> 00:01:20,172 with closures that can throw errors. 24 00:01:20,172 --> 00:01:26,350 The rethrows keyword indicates to the compiler that the outer function, 25 00:01:26,350 --> 00:01:31,360 apply in our case, becomes a throwing function only if the closure 26 00:01:31,360 --> 00:01:35,810 passed in throws an error that is propagated to the current scope. 27 00:01:35,810 --> 00:01:39,870 In the first case, since the closure expression does throw an error, 28 00:01:39,870 --> 00:01:43,180 which we've indicated with this line of code then apply, 29 00:01:43,180 --> 00:01:47,810 in our case the outer function becomes a throwing function. 30 00:01:47,810 --> 00:01:52,820 The outer function propagates this error and becomes a throwing function itself. 31 00:01:52,820 --> 00:01:56,880 But in the second case, since no errors are thrown in the inner function, 32 00:01:56,880 --> 00:01:59,550 the outer function is not a throwing one. 33 00:01:59,550 --> 00:02:02,410 Remember when we learned about map and flat map? 34 00:02:02,410 --> 00:02:06,880 I mentioned that our function signature wasn't how the standard library 35 00:02:06,880 --> 00:02:08,331 function was written. 36 00:02:08,331 --> 00:02:12,680 Well, if I just write out some code to get that map function on screen. 37 00:02:12,680 --> 00:02:17,058 So, I'll say [1,2].map \$0, and 38 00:02:17,058 --> 00:02:21,440 then if I commend click on here, great. 39 00:02:23,720 --> 00:02:26,780 Okay, so my playground isn't working properly. 40 00:02:26,780 --> 00:02:30,650 Let me just switch pages and come back and there we go. 41 00:02:30,650 --> 00:02:32,100 That works better. 42 00:02:32,100 --> 00:02:35,950 If I command click on here to go to the function signature, 43 00:02:35,950 --> 00:02:38,380 you'll see that it is marked in the same way. 44 00:02:38,380 --> 00:02:41,230 So the inner transform function is a throwing function, 45 00:02:41,230 --> 00:02:44,820 so we can throw an error and then map rethrows. 46 00:02:44,820 --> 00:02:49,730 So, if our closure that we use as a transformation function throws an error, 47 00:02:49,730 --> 00:02:51,940 then map itself is a throwing function. 48 00:02:51,940 --> 00:02:53,820 Otherwise, it is not. 49 00:02:53,820 --> 00:02:57,260 This way we only need to use try on map and 50 00:02:57,260 --> 00:03:00,640 our apply function if the closure throws an error. 51 00:03:00,640 --> 00:03:03,220 Now, this brings up an interesting point. 52 00:03:03,220 --> 00:03:06,188 If a function argument is marked as throwing, 53 00:03:06,188 --> 00:03:10,310 how come we can pass in a regular non throwing closure? 54 00:03:10,310 --> 00:03:14,060 So, for example, apply takes a closure that is a throwing closure. 55 00:03:14,060 --> 00:03:16,730 But here, this is a non throwing closure. 56 00:03:16,730 --> 00:03:18,110 How is that possible? 57 00:03:18,110 --> 00:03:23,770 Regular functions are subtypes of throwing functions with the same signature. 58 00:03:23,770 --> 00:03:26,607 That means that given these two functions. 59 00:03:26,607 --> 00:03:34,148 Let me just write it out, so func someFunction(a: Int) throws. 60 00:03:36,786 --> 00:03:43,548 And func anotherFunction(a: Int). 61 00:03:46,169 --> 00:03:51,635 Over here, you can use anotherFunction wherever someFunction is expected, 62 00:03:51,635 --> 00:03:56,320 because anotherFunction is a subtype of someFunction. 63 00:03:56,320 --> 00:04:01,000 This means that the function signature is identical minus the throws bit. 64 00:04:01,000 --> 00:04:05,680 However, you cannot use someFunction where another function is expected. 65 00:04:06,800 --> 00:04:11,390 Okay, now that we know how to write our own closures that can throw errors, 66 00:04:11,390 --> 00:04:14,470 let's talk about memory considerations with closures.