Good question. Both are needed to separate the two concerns, are we done and does the head match. isDone makes sure we only take up to our limit. isMatch runs the predicate to check for a match.
They could both be combined into a single condition and eliminate the variables completely, but I like to break my if’s out so the intent of the code is clear.
One thing about this code that I don’t quite like is how isMatch has knowledge about isDone. This breaks single responsibility a little bit. I think it would be better to turn isDone into a function.
I hope this answers your question.