Tytuł mówi wszystko, naprawdę; Iterowanie nad zbieraniem, przy zachowaniu stanu między pętlami i kończącej iteracji w oparciu o warunek zakończenia, oprócz po prostu wyczerpania elementów może być najczęstszym wzorcem do wykonania czegokolwiek w imperatywnym programowaniu. Wydaje mi się jednak, jakby coś gentleprogrammers funkcjonalne zgodził się nie rozmawiać, a przynajmniej nigdy nie napotkał idiom dla niego lub semi-standaryzowanego nazwy takie jak z map
, fold
, reduce
itpCzy istnieje pojęcie "fold with break" lub "find with accumulator" w programowaniu funkcjonalnym?
często używam kod śledzenia w 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
}
}
}
Ale to jest brzydkie. Ilekroć próbuję bardziej deklaratywny podejście, przyjdę jeszcze dłuższy i prawie na pewno wolniejszego kodu, podobny do:
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
(wariant bardziej funkcjonalne użyłby List
s lub Stream
s, ale iteratory mają zapewne mniejsze obciążenie niż konwersji items
do Stream
, jako domyślna implementacja dla tego ostatniego używa i tak pod iteratorem).
Moje pytania są następujące:
1) Czy pojęcie to ma nazwę w programowania funkcyjnego, a jeśli tak, to jaki jest wzór związany z jego realizacją?
2) Jaki byłby najlepszy (tj. Zwięzły, ogólny, leniwy i najmniejszy narzut) sposób wdrożenia go w scala?
Nigdy nie rozumiem, dlaczego nie ma standardowej implementacji. Tak. rekurencja ogona jest sposobem na zrobienie tego, ale jest nieco brzydka (i wymaga funkcji pomocnika, dla której trzeba znaleźć nazwę, która zawsze wydaje mi się trochę zakodowana). .mapUntil' i 'foldLeftUntil' etc wydają mi się przydatne ... –