• 函数工厂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 结合函数式编程,蕴藏着惊人的潜力。

  • 相关阅读:
    Centos7配置编译Tenflow1.15 GPU版本笔记
    今年有哪些便宜的国外域名注册商?
    VPS,域名,主机,建站主题,2020黑色星期五优惠大放送
    这些个挂机项目,赚点小钱玩玩
    WPF管理系统开发框架搭建指南,2020从入门到放弃
    智和信通助力荆门电教馆及六所市直学校实现网络智能化运维管理
    智和网管平台政企信创网管监控运维可视化方案
    智和网管平台与统信操作系统完成认证 强力支撑信创国产替代进程
    GIT基础操作与理解
    高数复习一(数列极限)
  • 原文地址:https://www.cnblogs.com/lovesqcc/p/12178211.html
Copyright © 2020-2023  润新知