如何使用 toolz 制作总是 returns 列表的 curry 版本的地图

How to make a curry version of map that always returns list using toolz

如果我使用

导入 toolz
from toolz.curried import *

那么map会自动变成柯里化形式,所以

map(func,[[1,2],[3,4]])

可以写成

map(func)([[1,2],[3,4]])

但 curried map 总是 return 一个可迭代对象。我的方法是定义一个总是 return 列表的 curried lmap。但简单的尝试

lmap=compose(list,map)

不行,例如

lmap(len)([[1,2],[3,4]])

会给

---------------------------------------------------------------------------
TypeError Traceback (most recent call last) in () ----> 1 lmap(len)([[1,2],[3,4]])

C:\ProgramData\Anaconda3\lib\site-packages\toolz\functoolz.py in
call(self, *args, **kwargs)
466 ret = self.first(*args, **kwargs)
467 for f in self.funcs:
--> 468 ret = f(ret)
469 return ret
470

TypeError: 'curry' object is not iterable

那么如何定义一个柯里化的lmap

你叫法不对。 map 传递给 compose 是柯里化的,但不是整个表达式。当你称它为

lmap(len)([[1,2],[3,4]])

它将 len 传递给 lmap 它 returns toolz.functoolz.curry 等同于

map(len)

然后尝试在其上调用 list

list(map(len))

这显然行不通。如果它没有失败,完整的表达式将等同于:

list(map(len))([[1,2],[3,4]])

而您正在寻找的电话是:

list(map(len), [[1,2],[3,4]])

所以实际上柯里化在这里没有多大意义。

您可能需要以下几行内容:

def lmap(g): return compose(list, map(g)) 

可以根据需要调用:

>>> lmap(len)([[1,2],[3,4]])
[2, 2]

但老实说这个问题看起来有点人为 - toolz 的最大优势在于统一的惰性。转换为 list 会丢弃大部分内容。

这个问题目前在 google 工具错误 'curry' object is not iterable 结果中排在首位。另一种触发此处尚未提及的错误消息的方法是尝试将 toolz.curried.pipe 与柯里化迭代器一起使用,就好像 pipe 本身被柯里化了一样:

>>> transform = pipe(
    map(lambda x: x + 1),
    map(lambda x: x + x)
    )
>>> list(transform([3,4,5]))
TypeError: 'curry' object is not iterable

这里第一个柯里化映射作为最后一个参数传递给第二个; 尽管从 curried 命名空间中重新导出,但 pipe 没有被 curried。解决方案是升级到 toolz 版本 0.10.0 如果还没有使用它并使用 toolz.curried.compose_left 代替它实际上是一个 curried pipe:

>>> transform = compose_left(
    map(lambda x: x + 1),
    map(lambda x: x + x)
    )
>>> list(transform([3,4,5]))
[8, 10, 12]