函数工厂Curry的威力

Posted lovesqcc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数工厂Curry的威力相关的知识,希望对你有一定的参考价值。

概述

“完全”函数式编程 一文中,我们初步感受了函数式编程的力量:以非常简洁的代码,通过组合任何短小的简单函数,实现更加复杂功能的复合函数。

有小伙伴可能会问: 既然函数是这么重要的原材料,那么从哪里可以获取这么多原材料呢 ?总不成,一个个去定义吧。别急,Curry 提供了批量生产函数的能力,—— 如果星云是恒星的工厂,那么,Curry 就是函数的工厂。

本文将以 Groovy 为示例,讲解 Curry 的特性及能力。

基础知识

小伙伴都学过多元函数,比如 f(x,y) = x^2 + y ,当 y = 0 时,就变成 f(x) = x^2 平方函数; 当 x = 1 时,就变成 f(y) = 1+y 线性函数。 Curry ,通俗地说,就是将多变量的函数,通过逐个因变量赋值,从而批量生成函数的能力。

如下代码所示: def closure = { x,y -> x^2 +y } 定义了一个二元函数 f(x,y) , rcurry(0) 即是将 y 赋值为 0 (右边的参数),这样就得到了一元函数 square(x) = x^2 ; curry(1) 即是将 x 赋值为 1 (默认是左边的参数),就得到了 linear(y) = 1+y 。 嗯,就是这么简单。

class Basics {

    static void main(args) {
        def closure = { x,y -> x * x +y }
        def square = closure.rcurry(0)

        println((1..5).collect { square(it) })

        def linear = closure.curry(1)
        println((1..5).collect { linear(it) })

    }
}

输出结果:

[1, 4, 9, 16, 25]
[2, 3, 4, 5, 6]


实际应用

那么 Curry 有什么实际应用呢 ? 总不能只停留在数学的领域里。 实际上 Curry 的能力非常强大。我们来实现一个通用调用器。在实际工程中,常常需要调用具有相同参数的函数,或者对不同的对象进行相同的处理。

假设有两个订单处理函数: cancel, complete ,有一个列表排序函数 sort:

   def static sort(list) {
        list.sort()
        return list
    }

    def static cancel(order) {
        println ("cancel: " + order.orderNo)
    }

    def static complete(order) {
        println ("complete: " + order.orderNo)
    }

class OrderParam {
    def orderNo
    def shopId
}

可以定义一个二元函数 generalCaller ,可以对指定的参数对象 param 使用指定的 handler 进行处理。

def generalCaller = { param, handler -> handler(param) }

现在,来看怎么使用:

第一种方式:指定参数对象。 可以构造一个订单对象,使用 Curry ,就得到了可以处理这个订单的函数处理器 orderProcessor, 然后就可以传入不同的订单处理器进行处理。this.&method 是 Groovy 对函数的引用。

def orderProcessor = generalCaller.curry(new OrderParam(orderNo: 'E0001', shopId: 55))
orderProcessor(this.&cancel)
orderProcessor(this.&complete)

第二种方式,指定处理器。 就得到了一个对参数进行排序的函数 sort(param) , 然后传入不同的可排序对象进行处理:

def sorter = generalCaller.rcurry(this.&sort)
println sorter([4,7,2,6,1,3])
println sorter(["i", "have", "a", "dream"]) 

是不是非常灵活 ? 在 “函数柯里化(Currying)示例” 一文中,使用 Curry 实现了一个简易的文件处理框架。

小结

Curry 可以将高维函数逐步降维,批量生成大量的低维函数。 如果有一个 N 维函数,思考下,通过 Curry ,可以生成多少个低维函数 ?Curry 结合函数式编程,蕴藏着惊人的潜力。

以上是关于函数工厂Curry的威力的主要内容,如果未能解决你的问题,请参考以下文章

ActionScript 3:curry 函数如何工作?

快速写curry函数和compose函数

手写curry函数,实现函数柯里化

数组原生api以及es6+函数式编程(curry)实现lodash函数

curry 时的 Groovy 错误

10.curry 方法