One nice aspect of laziness, is that it makes it easy to deal with infinite amount of works. Just do everything only when it is demanded. Following this principle, we look at ways to define and manipulate infinite streams. You saw that all elements of the stream except the first one are computed only when they're needed to produce a result. One maybe surprising possibility this opens is to define infinite streams. So, for instance the stream of all integers starting from a given number, could be define like this. It would say, def from of an n equals the stream consisting of n followed by from n + one. And normally, of course, this would be a non-terminating recursive computation but because the stream const operator is lazy in its right operands, the from n + one here would be actually calculated only if somebody is interested in the second element of the stream that's defined here. So, using from, we can now write infinite streams, for instance, the string of all natural number would be from zero or the stream of all multiples of four could be the stream of all natural numbers, mapped by times four. So, each, take each the natural number, multiply it by four, that gives the stream that returns all multiples of four. So, let's see this in a worksheet. I've already define from, so, And the stream of natural numbers would be from zero, Stream of multiples by four, Would be the natural numbers mapped by times four. To see it in action, I could then take m4s and take, let's say, first hundred elements, And convert the whole thing to a list which would force it so there would indeed see the list that contains the first hundred multiples of fours. But, of course, I could go higher I could take, take the first thousand and I would get the first thousand elements and so on. Now, one problem where we can put these techniques to good use is in the calculation of prime numbers. There's actually a very ancient algorithm called the Sieve of Eratosthenes to calculate these numbers. The idea is as follows, we start with all integers starting from two. So, three, four, five, six, And so on. We take the first number, that's a two and that's a prime number. We will then eliminate all multiples of two so that will be the six, the eight, the ten. The first number left in the resulting output stream is three, and that's a prime number. We then eliminate all multiples of three, so the six, is already eliminated, twelve is already eliminated, fifteen. The first number that's left in the stream is five, and that's a prime number. We eliminate all multiples of five, and so on. So, each step, we take the first element of the remaining stream of numbers. That one is a prime number. We eliminate all its multiples and we repeat. So, here's a function that implements this principle to the letter. To sieve a given stream of numbers S, what we do is we take the first number in the stream, So that would be our presumed prime number. And we follow it with all numbers that are not multiples of the first number. So, we take the rest of the stream, and we filter it with the predicate that we say, well, the number [unknown] the S, the first number. The s.head, must be different from zero. So, once we have the sieving method, obtaining all prime numbers is really easy. We simply say the prime numbers is sieve of all the integers from two. Let's try it out. Primes takes, let's take the first prime numbers and convert it to a list. And there you go. The first prime numbers here on the right. So, let's get back to square roots one more time. The previous algorithms we've seen for the square root algorithm always mixed determination criterion is good enough with the method to calculate new approximations. With streams at our disposal, we can now express the concept of a converging sequence without having to worry about determination criteria. So, we could write a stream that represents all the successive approximations of, of a square root of a given number. The thing we would do is we would have the usual improved method. And then, we would say, well, we have a lazy val guesses which is a stream of double, and the guesses start with one. And each successive value is obtained by mapping the improved function over guesses. So, this might look highly alarming to you, a little bit like a snake eating it's tail, because what happens here is that you apply a map operation on the value that you're about to define. So, won't this blow up in an infinite recursion? Well, again, no. Because we have the operation stream cons here, which is lazy in its right operand So, everything actually works out as it should. You can convince yourself by going to the worksheet. I have given you precisely the same stream method. So, let's try to apply this to a number. Let's say four. Take the first ten elements and print it out. So, what we would get is a perfectly good stream of approximations to the number four, Which after a couple of iterations, converges to 2.0. So now, we have decoupled the idea of a converging sequence from determination criterion. Of course, we can add determination criterion later. We see that here. So, we have to find the is good enough function as before, and we can then subject our square root stream to a filter method of all the elements that are good enough approximations. So, let's do that in the worksheet. I've added a good enough method and then, let me just filter that. Filter is good enough with respect to my number four. And again, I want to show, again, I want to show the first ten elements. So, what you see now is you get a stream of solutions that are all already good enough approximations to the actual square root value, so you could just take the first one of that stream, and return that as the result of your computation. So, here's a quiz for you. Consider the following two equivalent ways to define an infinite stream of multiples of a given number N. You could write, from one map times n, as we've seen, But you could also write from one filter modular N equals zero. Both expressions would give you the stream of multiples of N. But which of the two expressions generates its results faster? Would it be that expression here or the filter down there? So, let's see how these two expressions would behave. Let's take, for the sake of the example, N equals three. So, the first expression would produce, first, all the elements of the natural numbers starting from one, and immediately multiply each of these by three. So, it would yield, in that order, three, six, nine, twelve, and so on. The second expression would produce all natural numbers as before. And then, it would filter these numbers to keep only those that are divisible by three. So, it would keep the filter operations that would now keep every third number in the stream. So, by that argument, the map operation is more efficient because it doesn't generate unnecessary stream elements that are filtered out afterwards. So, my vote goes to answer one.