Hello, in this video, I want to illustrate the different styles of loops in more examples. We will see that recursive methods are especially useful to deal with recursive data structures. Let's write a program that checks whether a bowl passes through a hoop, given the shot direction and force. We are interested in the position of the ball over time. We model the position of the ball with a case class position defined by the x and y coordinates. We assume that these methods, distance to that position and distance to line, are already implemented. In the companion object of position we create two specific positions, the position of the player and the position of the hoop. In this example, distances are in meters. For convenience, we also define these types, angle and speed, which will make the code easier to read. We want to implement this method isWinningShot that takes an angle and an initial speed and returns whether the ball passed through the hoop or not. The intuition behind the algorithm is the following, we want to compute the successive positions of the bowl over time and the algorithm terminates in two conditions. If the bowl passes through the hoop, this is a winning shot so we want to return true. But if the bottle ends up too far on the ground or beyond the hoop, this is a failed shot so we return false. To check whether the ball passed through the hoop, we compute the distance between the center of the hoop and the straight segment made of successive positions of the ball. We want to compute the successive segments of the trajectory of the ball. We begin with these definitions, the initial horizontal and vertical speed of the ball, v0X and v0Y, and the initial horizontal and vertical position of the ball, p0X and p0Y, which is initialized to the position of the player. We create this value g for the gravitational constant. Then we define an auxiliary method, goes through hoop that takes a line as parameter and returns whether this line goes through the hoop or not by computing its distance to the hoop. We define another auxiliary method is not too far that takes the position of the ball as a parameter and checks that the ball did not hit the ground yet and that it is not further than the hoop. Last, we define this position method, which computes the position of the bowl at a given time t by using the equations of motion. We can now implement the loop of the algorithm. We will start with a solution based on collections and in this example we are going to use a new collection type named lazy list. You can think of lazy lists as list whose elements are computed only when needed. That is, when we iterate over them with a method like foldLeft, for instance. For example, lazy list that from zero constructs an infinite lazy list with the elements 0, 1, 2 and so on. To implement our algorithm, we start by computing the values of time starting from zero. Here, timings represents an infinite collections of time values starting from zero. We want to compute the successive segments of trajectory of the ball. To achieve this, we first compute the positions of the bowl over time by using the operation map under timings. Here, positions represents an infinite collection of position values. To get the segments of trajectory, we pair every position with the next one in the collection of positions by using the method zip. The method zip takes two collections and then returns a collection containing pairs of elements taken from each collection. Now, we use the method takeWhile to end the collection as soon as we compute a position that is too far. Finally, we use the method exists to iterate over every segment of the trajectory until we find one that goes through the hoop, or until we reach the end of the correction, in which case we return false. This is an example of use of the isWinningShot method. Here is a visual representation of the algorithm. We start by computing the infinite collection of timings, 0, 1, 2 and so on, then we compute the positions by transforming every time value into its corresponding position, then we compute the segments of trajectory by pairing together every position with its successor. Here we define an end to our collection of segment, and finally, we compute every segment until we find one that goes through the hoop, or until we reach the end of the collection. Let's switch back to the code editor and rewrite the algorithm with the while loop instead. In every iteration of the loop, we will compute a new segment of trajectory and check whether it goes through the hoop or not. We want a variable isWinning that stores this information and that we will eventually return. To compute each segment of trajectory, we need two positions the previous position and the next position. In every iteration we update, we want to update the previous position to be the next position, so this is going to be a variable. Each position is computed according to the canned value of time which we increment in every iteration of the loop. We keep iterating as long as the ball is not going too far, and we stop if we find a winning segment. This is it for the imperative solution. Let's rewrite the algorithm again, but with a recursive method this time. We will loop over time and return a Boolean value. It is often easier to start with the case where we stop the algorithm. In our case, we stop if the ball goes too far, so we return false here. Otherwise, we compute the current segment of trajectory, which is made of the current position and the previous position. Now we have two cases again. If the current segment of trajectory goes through the hoop, we immediately return true. Otherwise, we compute the next iteration, and we can see below the same column two is winning shot. Let's try with another example. We want to manage tasks. Task have a name, a duration, and they can depend on other tasks to be finished before we can start working on them. In this example, before you can start deploying your application, you first need to write it, which is modeled by this task, hack. Before you can start hacking, you need to set up your machine by installing an IDE and by installing a couple of tools with CS setup. The question we want to answer is, when can we expect the task, deploy to be finished at best? We see that the task itself takes some time, but we also need to take into account the time it takes to complete the tasks it depends on. Here hack, and the task hack also needs to wait for the longest of both CS setup and ID to finish. Both tasks, CS setup and IDE can be run in parallel. We can model this problem with the following case class, task, which takes a name, a duration, and a list of requirements that are still task. This is a recursive definition. We can instantiate our model like this to represent what we had in the previous diagram. Let's switch to the code editor now. We want to write a method, total duration that takes a task as a parameter and returns the time it takes to complete including all the tasks it depends on. The implementation is the duration of the task plus the maximum duration of the tasks it depends on. What is the maximum duration of a list of tasks. Let's start with the easy case. If the task does not depend on other task, then the list of requirements is empty and we return a duration of zero. Otherwise, there is at least when task, head and possibly other tasks, tail. We want to take the maximum of the total duration of the head task and of the maximum duration of the tail tasks. We need to recursively call max total duration on the tail list of tasks and to also call total duration on the head task. The implementation is complete and we can see that the time here is 15. It is worth noting that there is already a method max option and list that we can use to compute the maximum total duration of a list of tasks. Like this. It returns an option because in case the list is empty, there is no maximum. We use "getOrElse" to return zero in that case. Let's switch back to the slides. I wanted to highlight a point about the way I wrote the recursive implementation of Max total duration. The type list is a recursive type because the tail of the list is itself a list and you can see that we are so recursively apply the method max total duration to the tail list. The structure of our recursive method follows the structure of the list data type. This pattern is called structural recursion, and marginally, recursive data types are easy to process with structurally recursive algorithms. To summarize, we have seen several styles of loops in a couple of examples. Here is some general advice, often exploring the solution space of a problem is convenient to express with the existing collection operations. Generally, recursion works well with recursive data types. According to the situation, just pick the solution that works better for you and your team.