3

在 haskell 中,运算符的初始值foldl显然是强制性的

Prelude> foldl (+) 0 [1]
1
Prelude> foldl (+) 0 []
0
Prelude> :t foldl
(a -> b -> a) -> a -> [b] -> a

但是在reduce函数(或functools.reduce)中,初始值是可选的

reduce(function, sequence[, initial]) -> value

唯一需要初始值的时候是序列为空时。这与haskell中的行为一致。Python中的Doesreduce假设如果序列的大小为1;然后它在内部处理这些极端情况?

>> reduce(operator.sub, [1])
1
>> reduce(operator.mul, [1])
1
>> reduce(operator.add, [1])
1
4

2 回答 2

6

回想一下,在 Haskell 中有两种版本的折叠——一种采用某种结果类型的种子,另一种假定种子是序列的第一个元素。

foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
        where
            go []     = z
            go (y:ys) = y `k` go ys

foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 _ [x]            =  x
foldr1 f (x:xs)         =  f x (foldr1 f xs)
foldr1 _ []             =  errorEmptyList "foldr1"

foldr使用序列的初始元素作为第一个状态。

还有一个重要的区别:通过使用序列的第一个元素作为输入状态,foldr1被限制为返回与输入列表相同类型的数组。foldr但是可以返回一些不同的类型。

于 2012-06-04T14:35:26.967 回答
5

手册

如果没有给出初始化程序并且可迭代只包含一个项目,则返回第一个项目


我也想对此发表评论:

唯一需要初始值的时候是序列为空时

这并不完全正确。在折叠操作中,您通常总是假设您有一个较早的结果可以使用。如果您的折叠操作是将元素附加到列表中,则初始元素可以是空列表,因此您可以向其中添加元素。更一般地,当函数的返回类型与列表中元素的类型不同时,总是需要初始值。

于 2012-06-04T14:30:22.317 回答