Название говорит об этом, действительно; итерация по коллекции при сохранении состояния между циклами и завершающей итерации на основе условия завершения в дополнение к простому исчерпанию элементов может быть наиболее распространенной схемой для выполнения чего-либо в императивном программировании. Мне кажется, что это что-то функциональное, мягкопрограммируемое, соглашалось не говорить, или, по крайней мере, я никогда не сталкивался с его идиомой или полу-стандартизованным именем, например map
, fold
, reduce
и т.д.
Я часто использую следующий код в scala:
implicit class FoldWhile[T](private val items :Iterable[T]) extends AnyVal {
def foldWhile[A](start :A)(until :A=>Boolean)(op :(A, T)=>A) :A = {
if (until(start)) start
else {
var accumulator = start
items.find{ e => accumulator = op(accumulator, e); until(accumulator) }
accumulator
}
}
}
Но это уродливо. Всякий раз, когда я пробую более декларативный подход, я прихожу с еще более длинным и почти наверняка более медленным кодом, сродни:
Iterator.iterate((start, items.iterator)){
case (acc, i) if until(acc) => (acc, i)
case (acc, i) if i.hasNext => (op(acc, i.next()), i)
case x => x
}.dropWhile {
case (acc, i) => !until(acc) && i.hasNext
}.next()._1
(Более функциональный вариант использовал бы List
или Stream
s, но итераторы имели, возможно, меньшие накладные расходы, чем преобразование items
в Stream
, поскольку реализация по умолчанию для последнего использует итератор в любом случае).
Мои вопросы:
1) Имеет ли эта концепция название в функциональном программировании, и если да, то каков шаблон, связанный с его реализацией?
2) Что было бы лучшим (то есть кратким, общим, ленивым и с наименьшими издержками) способом реализовать его в scala?