函数是否有返回其参数的位置扩展版本的名称



在这个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表示。但uncurry3uncurry4等不会不合时宜。

所以我说得对,它"隐约让人想起咖喱",因为事实恰恰相反。


第二种解释是取一个函数,该函数接受一个有意可变数量的参数,并返回一个接受单个列表的函数。

因为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所指出的,原始问题中uncurryzipmap的特定组合正是zipWith。事实上,HLint默认情况下包括一个规则,用对zipWith的单个调用来替换这个复杂的构造。


我希望这一切都会过去,伊恩。

相关内容

  • 没有找到相关文章

最新更新