在此Python代码中考虑splatter
:
def splatter(fn):
return lambda (args): fn(*args)
def add(a, b):
return a + b
list1 = [1, 2, 3]
list2 = [4, 5, 6]
print map(splatter(add), zip(list1, list2))
将n-ary函数映射到n个压缩序列似乎是一个很常见的操作,可能已经有了这个名称,但我不知道我在哪里找到它。它模糊地唤起了人们的讨论,似乎可能还有其他相关的以论证为中心的HOF,我从未听说过。有谁知道这是否是一个“众所周知”的功能?在讨论时,我目前仍然坚持使用问题标题中使用的笨拙语言。
map
会自动执行此操作。你可以写:
map(add, list1, list2)
它会做正确的事情,为您省去splatter
功能的麻烦。唯一的区别是zip
返回一个列表,其长度是其最短参数的长度,而map
使用None
扩展更短的列表。
答案 0 :(得分:1)
我认为zipWith
是您正在搜索的函数(此名称至少在Haskell中使用)。它甚至更普遍。在Haskell zipWith
定义如下(第一行只是类型):
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
zipWith _ _ _ = []
你的例子就像是
zipWith (+) [1, 2, 3] [4, 5, 6]
由于我不太了解python,我只能指向“zipWith analogue in Python?”。
答案 1 :(得分:0)
我在“问题问题”列表中随机看到了这一点,并对我现在知道答案感到惊讶。
我问过这个函数有两种解释。
第一个是我的意图:采用一个函数,它接受固定数量的参数并将其转换为一个函数,将这些参数作为固定大小的列表或元组。在Haskell中,执行此操作的函数称为uncurry
。
uncurry :: (a -> b -> c) -> ((a, b) -> c)
(为了清楚起见,额外的parens。)
很容易想象将它扩展到两个以上参数的函数,尽管它不能在Haskell中表达。但uncurry3
,uncurry4
等不会不合适。
所以我说得对,“模糊地引起了讨论”,因为它恰恰相反。
第二种解释是采用一个函数,该函数采用有意数量的可变参数并返回一个带有单个列表的函数。
因为splat
在Python中是一个非常奇怪的语法结构,所以很难说明这一点。
但是,如果我们想象一下,JavaScript,它具有一流的命名函数“splatting:”
varFn.apply(null, args)
var splatter = function(f) {
return function(arg) {
return f.apply(null, arg);
};
};
然后我们可以将其重新描述为仅仅部分应用“apply
”函数:
var splatter = function(f) {
return Function.prototype.apply.bind(f, null);
};
或者使用Underscore's partial
,我们可以提出无点定义:
var splatter = _.partial(Function.prototype.bind.bind(Function.prototype.apply), _, null)
是的,这是一场噩梦。
(_.partial
的替代方案需要定义某种swap
帮助程序,我认为它的可读性会更低。)
所以我认为这个操作的名称只是“apply
的部分应用”,或者在Python的情况下它几乎就像是splat运算符的section - 如果splat是“实际”操作员。
但原始问题中uncurry
,zip
和map
的特定组合恰好是zipWith
,as chris pointed out。实际上,HLint默认includes a rule只需调用zipWith
即可替换此复杂构造。
我希望通过伊恩来解决问题。