Break Out of reduce()
On how you can escape from
reduce() method earlier if you want
reduce() is a very useful method in the Swift Standard Library. It works like a
for in loop (it is the one in fact), but it’s designed specifically to calculate a single value out of the elements in the collection. There is only one subtle difference — we cannot do this:
In fact we cannot do this out of the box, but the goal of my post is to show you how you can extend the
Sequence protocol to achieve such goal and be able to break out of
We can do this:
But now the
if statement becomes part of the
nextPartialResult closure and clutters the logic here. That’s not good. Let’s imagine a better solution. How about this:
That’s better — let’s see how we can implement it. The original reduce method is implemented on the
Sequence protocol, so let’s put an overload in the extension:
Looks good, let’s give it a try:
Reduce a sequence of numbers with
+operator until the partial sum becomes greater then 5.
It reads nicely, but there is one more issue.
If you run it in a playground (you can find my playground here) you’ll see “(6 times)”, and yes — if you increase the size of your sequence to 500 elements it’ll say “(501 times)” times. That’s because our condition closure is getting called n times, (where n is the size of the collection, + 1 is a call to
reduce). So why do we need to invoke it as many times?
Computers and smartphones are fast, but we don’t want them to be wasteful and behave like that dog. In our case 3 iterations is all we really need…
In our overload (as in the original declaration) of the
reduce method we can see that
nextPartialResult that we’re implementing in our overload can throw an exception, so why not leverage it - throw an exception when we pass our condition, handle it so it won’t escape the scope of our extension and return a result.
To achieve it we’ll need an
Error conforming type that will pass a
Result object to the catch closure:
To finish it let’s have a full-fledged implementation, that allows us to make a “break it or make it” decision not only based on the partial result, but on the current element of the collection as well (although if it’s gonna be sth like
element == someThing you should rather use
Here it is:
There is another variation of it and you should use it if you expect to reduce collection while the given condition is true:
It gives a different result, so you can use it when you don’t want to include the element above condition (as it is a case in
So that’s it!
I hope you enjoyed my second post. Feel free to give it a try, you can find the sample playground here.
I’m Maciek Czarnik
iOS Developer, musician, maker. Passionate about building beautiful, robust, useful and user-friendly apps. Contact firstname.lastname@example.org for project inquiries.