您通常使用纯函数式编程中的列表做什么?
显然,我们map f [x0; x1; x2]
会生成[f x0; f x1; f x2]
和fold f acc [x0; x1; x2]
,会产生f (f (f acc x0) x1) x2)
。
对于map
,调用f
之间不会传输任何信息;对于fold
,f
生成的所有信息都会通过累加器acc
在下一次调用中重新注入。
我还看到flatmap
之类的内容会在map f
返回列表时连接f
生成的列表,而for_all
将谓词应用于所有元素列表,但这些只是map
和fold
的特殊情况。
我可以考虑一些产生列表但在迭代期间保留累加器的中间件(OCaml语法):
let rec map_acc ~f acc = function
| [] -> []
| x::xs -> let (y, acc) = f x acc in y::(map_acc ~f acc xs)
问题:
map_acc
函数式编程中的常用概念吗?注意:
以下是使用map_acc
生成运行总和的示例:
let sums xs = map_acc ~f:(fun x sum -> let sum = sum + x in (sum, sum)) 0 xs
sums [3; 5; 6; 9]
生成[3; 8; 14; 23]
。授予sums
可以使用fold
和精心设计的累加器来实现,但mac_acc
更简单。
答案 0 :(得分:2)
map_acc
看起来更像一般scan_left
:
let scan_left f init list =
let _, xs = List.fold_left
(fun (acc, coll) elt ->
let acc' = f acc elt in acc', acc'::coll)
(init, []) list in
List.rev xs
scan_left (+) 0 [3; 5; 6; 9] => [3; 8; 14; 23]
这个函数和变体在几种函数式语言的标准库中以各种名称出现,但不是OCaml。
这些函数都不值得被称为原语。