You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First we call `tails` with the list in which we're searching.
349
349
Then we go over each tail and see if it starts with what we're looking for.
350
350
351
+
Maybe you're surprised to see `foldr` being used here, instead of `foldl'`.
352
+
Why aren't we going through the list simply from left to right, like a normal person?
353
+
Ah, but we are!
354
+
You see, `foldr` does not *really* go through lists from right to left.
355
+
It actually walks the list from left to right, just like `foldl'`.
356
+
The real difference is not the direction, but the way the end result is composed.
357
+
358
+
In a strict left fold, at every step the accumulator is immediately updated.
359
+
Nice, no time or space wasted.
360
+
The catch is that `foldl'` refuses to stop until it has reached the end of the list.
361
+
The accumulation function you pass it has no say in the matter.
362
+
This is unfortunate: if we have already found what we're looking for, there is little point in continuing the search!
363
+
364
+
This is where the lazy right fold comes in.
365
+
`foldr` actually gives its accumulation function some control, which allows us to stop searching early.
366
+
At each step `foldr` is like: hey combining function, here's this list element that I found.
367
+
Do with it what you will.
368
+
I'd rather not go further down the list, because I'm lazy, but if you really need me to I will and I'll pass the result of that to you as a second argument.
369
+
If the combining function at any point does not really need its second argument, then the list walking can stop.
370
+
But if it does need its second argument then, well, the walk must go on.
371
+
372
+
Coming back to the implementation of `search`, we see an element--accumulator combining function appropriately named `step`.
373
+
From `foldr` it receives elements of `tails haystack`, which are themselves lists and therefore called `segment` in this code.
374
+
For each `segment` we check whether it matches the `needle`.
375
+
If it does, then we're done.
376
+
No need to even look at the second argument, we can just return `True` immediately and thereby stop the search.
377
+
But if it does not match the `needle`, then we need to continue.
378
+
Fortunately, `foldr` also passes `step` a second argument: the promise to continue the search, should it need it to.
379
+
I have cheekily chosen to call this promise `continue`.
380
+
Not yet having found our `needle`, we have no choice but to take `foldr` up on its promise.
381
+
We therefore return `continue`.
382
+
351
383
With that, we actually just made a function that behaves like `isInfixOf`{.label .function}.
352
384
`isInfixOf` searches for a sublist within a list and returns `True` if the sublist we're looking for is somewhere inside the target list.
0 commit comments