在这个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元函数映射到n个压缩序列上似乎是一种足够常见的操作,可能已经有了它的名称,但我不知道在哪里可以找到它。它隐约让人想起咖喱,而且似乎还有其他我从未听说过的以争论为中心的相关HOF。有人知道这是否是一个"众所周知"的函数吗?在讨论这个问题时,我目前被问题标题中使用的那种尴尬的语言所困扰。
编辑
哇,Python的map
会自动做到这一点。你可以写:
map(add, list1, list2)
它会做正确的事情,省去splatter
调用函数的麻烦。唯一的区别是,zip
返回的列表的长度是其最短参数的长度,而map
使用None
扩展较短的列表。
我认为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 analog in python?"。
我在"问题"列表中随机看到了这一点,很惊讶我现在知道了答案。
我所问的函数有两种解释。
第一个是我的意图:获取一个接受固定数量参数的函数,并将其转换为一个接受这些参数作为固定大小列表或元组的函数。在Haskell中,执行此操作的函数称为uncurry
。
uncurry :: (a -> b -> c) -> ((a, b) -> c)
(为了清晰起见,增加了括号。)
很容易想象将其扩展到两个以上参数的函数,尽管它不能用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的partial
,我们可以得出无点定义:
var splatter = _.partial(Function.prototype.bind.bind(Function.prototype.apply), _, null)
是的,那简直是一场噩梦。
(_.partial
的替代方案需要定义某种swap
助手,我认为这会变得更不可读。)
因此,我认为这个操作的名称只是"apply
的部分应用程序",或者在Python的情况下,它几乎就像splat运算符的一部分——如果splat是一个"实际"运算符的话。
但正如chris所指出的,原始问题中uncurry
、zip
和map
的特定组合正是zipWith
。事实上,HLint默认情况下包括一个规则,用对zipWith
的单个调用来替换这个复杂的构造。
我希望这一切都会过去,伊恩。