https://www.gnu.org/software/guile/manual/html_node/SRFI_002d1-Fold-and-Map.html
Процедура схемы: fold proc init lst1 lst2 …
Процедура схемы: fold-right proc init lst1 lst2 …
Примените proc к элементам lst1 lst2 …, чтобы получить результат, и вернуть эторезультат.
Каждый proc вызов (proc elem1 elem2 … previous) ,где elem1 от lst1 , elem2 от lst2 и так далее.previous - это возврат предыдущего вызова к proc или заданный init для первого вызова. Если какой-либо список пуст, возвращается только init .
fold
обрабатывает элементы списка от первого до последнего.Далее показано обращение списка и выполняемые им вызовы:
(fold cons '() '(1 2 3))
(cons 1 '())
(cons 2 '(1))
(cons 3 '(2 1)
⇒ (3 2 1)
fold-right
работает через элементы списка от последнего к первому, т.е.справаТак, например, следующий код находит самую длинную строку и последнюю среди равных самых длинных,
(fold-right (lambda (str prev)
(if (> (string-length str) (string-length prev))
str
prev))
""
'("x" "abc" "xyz" "jk"))
⇒ "xyz"
Схемы свертывания поддерживают несколько списков, но я покажу вам, как настроить реализацию JavaScript так, чтобы онаработает с одним списком -
function reduce (fn, init, list) {
if (isNull(list))
return init
else
return reduce(fn, fn(list.car, init), list.cdr)
}
function reduceRight (fn, init, list) {
if (isNull(list))
return init
else
return fn(list.car, reduceRight(fn, init, list.cdr))
}
Поддержка нескольких списков достаточно проста благодаря поддержке JavaScript для параметров отдыха и аргументов распространения -
function some (fn, list) {
if (isNull(list))
return false
else
return fn(list.car) || some(fn, list.cdr)
}
function reduce (fn, init, ...lists) {
if (some(isEmpty, lists))
return init
else
return reduce
( fn
, fn (...lists.map(l => l.car), init)
, lists.map(l => l.cdr)
)
}
function reduceRight (fn, init, ...lists) {
if (some(isEmpty, lists))
return init
else
// exercise left for reader
// ...
}