什么时候应该使用函数咖喱?

When should I use function currying?

提问人:overexchange 提问时间:7/22/2014 最后编辑:martineauoverexchange 更新时间:2/7/2022 访问量:36525

问:

我什么时候应该以 cured 形式编写我的函数?不符合我的想法,需要纠正自己。

作为我学习链接的一部分,这就是我从函数咖喱中理解的。下面是一个示例:

def curry2(f):
    """Returns a function g such that g(x)(y) == f(x, y)

    >>> from operator import add
    >>> add_three = curry2(add)(3)
    >>> add_three(4)
    """
    def g(x):
        def h(y):
            return f(x, y)
        return h
    return g

在任何应用程序中,如果我知道参数的数量是固定的(比如 2 个参数)并且 函数名称是(说),那么我将定义函数并通过调用 直接在我的应用程序中使用它。normalise_rangedef normalise_range(x, y):normalise_range(x, y)

在任何应用程序中,如果我知道的话,参数的数量是固定的(比如 2 个参数), 但是函数名是变化的(可以是//我不知道..), 然后我将如上所示使用,它将接受所有接受两个参数的函数(固定)。normalise_rangeaveragedef curry2(f):

我的问题:

  1. 我的理解正确吗?
  2. 如果是,我们可以考虑对可变数量的参数的函数进行咖喱吗?
python 函数式编程

评论

2赞 user2357112 7/22/2014
为什么你决定是否咖喱一个函数与你是否提前知道这个名字有关?只要你能打电话,你就可以打电话,不用讨好。curry2(f)f(x, y)
0赞 NoDataDumpNoContribution 7/22/2014
参见 咖喱和部分应用有什么区别?
0赞 overexchange 8/3/2014
@user2357112我明白你的意思。
0赞 overexchange 8/3/2014
@Trilarion让我先了解一下,什么时候使用函数咖喱,然后我会想到比较和Function Curryingpartial application

答:

30赞 NoDataDumpNoContribution 7/22/2014 #1

函数咖喱的目的是从更通用的函数中轻松获取专用函数。您可以通过在不同的时间预设一些参数并在之后保持固定来实现这一点。

它与命名无关。在 Python 中,您可以随时轻松重命名变量/函数。

例:

def simple_function(a):
    def line(b=0):
        def compute(x):
            return [a+b * xi for xi in x]
        return compute
    return line

x = range(-4, 4, 1)
print('x {}'.format(list(x)))
print('constant {}'.format(simple_function(3)()(x)))
print('line {}'.format(simple_function(3)(-2)(x)))

x [-4, -3, -2, -1, 0, 1, 2, 3]
constant [3, 3, 3, 3, 3, 3, 3, 3]
line [11, 9, 7, 5, 3, 1, -1, -3]

现在这还不是那么令人兴奋。它只是用 type 的调用替换了类型的函数调用,这甚至可能被视为 Python 中不太优雅的风格。f(a,b,c)f(a)(b)(c)

但它允许您执行以下操作:

line_through_zero = simple_function(0)
print('line through zero {}'.format(line_through_zero(1)(x))) # only slope and x

这给了

line through zero [-4, -3, -2, -1, 0, 1, 2, 3]

因此,currying 的优点是您可以获得具有固定参数的专用函数,并且可以使用这些函数,而不是编写更通用的形式并在每次调用时设置固定的参数。

咖喱的替代方法有:和。因此,在实践中,咖喱可能很有用,但如果你愿意,你也可以绕过它。partiallambdadefault parameters

参见 Python 中的 Currying

评论

1赞 overexchange 7/23/2014
拥有专用功能(例如,在您的答案中)的优势是什么?现在,我认为,在我们有 3 个参数(比如)并且第一个参数已准备好(比如)的情况下,咖喱可能会很有用,所以我们在应用一个参数并等待来自第三方模块的其他两个参数(比如)后创建专用函数。你认为我们可以有这样的场景吗?line_through_zero
0赞 overexchange 7/23/2014
我的意思是,如果一个函数有两个参数,那么第一个参数在 place1 可用,然后创建部分应用的函数并多次传递给 place2,其中第二个参数 available.am 我正确吗?
1赞 Jonah 10/19/2017
“因此,currying 的优点是,您可以获得具有固定参数的专用函数,并且可以使用这些函数,而不是编写更通用的形式并在每次调用时设置固定的参数。主要优点是它允许通过组合创建新功能。
5赞 Nishant 3/13/2019 #2

咖喱至少有两个我能想到的优势:

1)它使你的代码(以及你的思维保持枯燥

假设你有一个这样的函数:

def call_me(context, args):
    ...

通过咖喱,您可以获得可以折腾的专用功能等。您不必再次重复上下文。context

2)从单个输入函数的角度思考比参数容易得多;不过,这有时是值得商榷的。n

Смотритетакже: 咖喱和部分应用有什么区别?

0赞 Fernando Magno Quintao Pereira 12/9/2021 #3

在许多方面,这种咖喱和参数对函数的部分应用的组合模拟了面向对象编程中我们所说的“工厂模式”。Currying 允许程序员创建专门的函数,正如其他人在这个论坛中指出的那样。例如,在下面检查这个(不优雅的)快速排序的实现:

leq = lambda x: lambda y: x <= y
gth = lambda x: lambda y: x > y

def qsort(L):
    if L:
        smalls = filter(gth(L[0]), L[1:])
        bigs = filter(leq(L[0]), L[1:])
        return qsort(smalls) + [L[0]] + qsort(bigs)
    else:
        return L

print(qsort([2, 4, 1, 4, 2]))