前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Groovy】闭包 Closure ( 闭包参数绑定 | curry 函数 | rcurry 函数 | ncurry 函数 | 代码示例 )

【Groovy】闭包 Closure ( 闭包参数绑定 | curry 函数 | rcurry 函数 | ncurry 函数 | 代码示例 )

作者头像
韩曙亮
发布2023-03-30 10:17:37
1K0
发布2023-03-30 10:17:37
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、闭包参数绑定


闭包 Closure 提供了 curry , ncurry , rcurry 方法 , 这

3

个方法可以将 闭包 进行 参数绑定 ;

  • curry 函数 : 从左到右 绑定 闭包参数 ;
  • rcurry 函数 : 从右到左 绑定 闭包参数 ;
  • ncurry 函数 : 指定从第
n

个参数开始绑定 闭包参数 ;

上述

3

个方法都会 创建一个新的闭包 , 需要使用 新的变量接收新创建的闭包 , 原来的闭包变量保持不变 ;

1、闭包参数绑定 curry 函数

从左到右绑定参数 ;

闭包参数绑定 curry 函数原型 :

代码语言:javascript
复制
    /**
     * 从左到右进行参数绑定
     * <p>
     * 典型用法:
     * <pre class="groovyTestCase">
     * def multiply = { a, b {@code ->} a * b }
     * def doubler = multiply.curry(2)
     * assert doubler(4) == 8
     * </pre>
     * 注:对闭包 vararg 类型的功能进行了特殊处理。
     * 如果使用vararg参数,则不会使用整个vararg数组,
     * 而是使用vararg数组的第一个参数,
     * 如下例所示:
     * <pre class="groovyTestCase">
     * def a = { one, two, Object[] others {@code ->} one + two + others.sum() }
     * assert a.parameterTypes.name == ['java.lang.Object', 'java.lang.Object', '[Ljava.lang.Object;']
     * assert a(1,2,3,4) == 10
     * def b = a.curry(1)
     * assert b.parameterTypes.name == ['java.lang.Object', '[Ljava.lang.Object;']
     * assert b(2,3,4) == 10
     * def c = b.curry(2)
     * assert c.parameterTypes.name == ['[Ljava.lang.Object;']
     * assert c(3,4) == 10
     * def d = c.curry(3)
     * assert d.parameterTypes.name == ['[Ljava.lang.Object;']
     * assert d(4) == 10
     * def e = d.curry(4)
     * assert e.parameterTypes.name == ['[Ljava.lang.Object;']
     * assert e() == 10
     * assert e(5) == 15
     * </pre>
     *
     *
     * @param arguments 要绑定的闭包参数
     * @return 返回已经绑定参数的新的闭包 
     */
    public Closure<V> curry(final Object... arguments) {
        return new CurriedClosure<V>(this, arguments);
    }

代码示例 :

代码语言:javascript
复制
        // 定义闭包变量 , 声明两个参数 a, b
        // 并为闭包指定默认值
        def closure5 = { a = 0, b = "Groovy" ->
            println "${a} : ${b}"
        }

        // 闭包有默认值 , 调用时可以不传入参数
        closure5()


        // 从左到右绑定 闭包参数
        def closure6 = closure5.curry(1, "Gradle")
        // 闭包有默认值 , 调用时可以不传入参数
        closure6()

执行结果 :

代码语言:javascript
复制
0 : Groovy
1 : Gradle

2、闭包参数绑定 rcurry 函数

闭包参数绑定 rcurry 函数是从右到左绑定参数 , 但是 参数的顺序还是从左到右的顺序 , 这点要注意 ;

闭包参数绑定 rcurry 函数原型 :

代码语言:javascript
复制
    /**
     * 从右到左绑定闭包参数
     * 根据普通的 curry()方法,参数在右侧而不是左侧提供。
     * 典型用法:
     * <pre class="groovyTestCase">
     * def divide = { a, b {@code ->} a / b }
     * def halver = divide.rcurry(2)
     * assert halver(8) == 4
     * </pre>
     *
     * curried参数的位置将被延迟计算,
     * 例如,如果有两个重载的doCall方法可用,
     * 则提供的参数加上curried参数将被连接,结果将用于方法选择。
     *
     * @param arguments 绑定的参数
     * @return 绑定参数后的新闭包 
     * @see #curry(Object...)
     */
    public Closure<V> rcurry(final Object... arguments) {
        return new CurriedClosure<V>(-arguments.length, this, arguments);
    }

代码示例 :

代码语言:javascript
复制
        // 定义闭包变量 , 声明两个参数 a, b
        // 并为闭包指定默认值
        def closure5 = { a = 0, b = "Groovy" ->
            println "${a} : ${b}"
        }

        // 闭包有默认值 , 调用时可以不传入参数
        closure5()

        // 从右到左绑定 闭包参数
        def closure7 =closure5.rcurry(2, "Java")
        // 闭包有默认值 , 调用时可以不传入参数
        closure7()

执行结果 :

代码语言:javascript
复制
0 : Groovy
2 : Java

3、闭包参数绑定 ncurry 函数

从第

n

个参数开始绑定闭包中的参数 ;

注意调用了 curry / ncurry / rcurry 方法后 , 所有的默认值都被覆盖清除了 , 如果 从第

2

个参数开始绑定闭包参数 , 则此时第一个参数也没有默认值了 , 调用时 , 必须传入第一个参数只才可以 , 否则运行时会报错 ;

闭包参数绑定 ncurry 函数原型 :

代码语言:javascript
复制
    /**
     * 从给定的索引处开始绑定闭包参数
     *
     * @param argument 要绑定参数的闭包
     * @return the 绑定参数后新创建的闭包
     * @see #ncurry(int, Object...)
     */
    public Closure<V> ncurry(int n, final Object argument) {
        return ncurry(n, new Object[]{argument});
    }

代码示例 :

代码语言:javascript
复制
        // 定义闭包变量 , 声明两个参数 a, b
        // 并为闭包指定默认值
        def closure5 = { a = 0, b = "Groovy" ->
            println "${a} : ${b}"
        }

        // 闭包有默认值 , 调用时可以不传入参数
        closure5()

        // 从第 n 个参数开始绑定闭包参数 ,
        // 注意调用了 curry / ncurry / rcurry 方法后 , 之前的默认值就覆盖了
        // 此时第一个参数没有值了
        // 调用时 , 必须传入第一个参数只才可以
        def closure8 =closure5.ncurry(1, "Kotlin")
        // 闭包的第一个默认值被取消 , 此时必须传入第一个参数的值才能执行该闭包
        // 否则报错
        closure8(3)

执行结果 :

代码语言:javascript
复制
0 : Groovy
3 : Kotlin

二、完整代码示例


完整代码示例 :

代码语言:javascript
复制
import org.codehaus.groovy.ant.Groovy

class Test {
    static void main(args) {


        // I. 接收默认一个参数的变薄


        // 定义闭包变量
        def closure = {
            println "Accept One Arguments : ${it}"
        }

        // 调用闭包
        closure.call("Hello");
        closure("Hello");


        // II. 不接收任何参数的闭包


        // 定义闭包变量 , 不允许传入参数
        def closure2 = { ->
            println "Not Accept Arguments"
        }

        // 传入参数会报错
        //closure2("Hello")

        // 调用闭包 , 不能传入参数
        closure2.call();
        closure2();


        // III. 接收一个自定义参数的闭包


        // 定义闭包变量 , 声明一个参数 a
        def closure3 = { a ->
            println "${a}"
        }

        // 调用闭包 , 不能传入参数
        closure3.call(1);
        closure3(2);


        // IV. 接收两个自定义参数的闭包


        // 定义闭包变量 , 声明两个参数 a, b
        // 在闭包中打印这两个参数
        def closure4 = { a, b ->
            println "${a} : ${b}"
        }

        // 调用闭包 , 不能传入参数
        closure4.call(1, 2);
        closure4(3, 4);


        // V. 为闭包参数指定默认值


        // 定义闭包变量 , 声明两个参数 a, b
        // 并为闭包指定默认值
        def closure5 = { a = 0, b = "Groovy" ->
            println "${a} : ${b}"
        }

        // 闭包有默认值 , 调用时可以不传入参数
        closure5()


        // 从左到右绑定 闭包参数
        def closure6 = closure5.curry(1, "Gradle")
        // 闭包有默认值 , 调用时可以不传入参数
        closure6()

        // 从右到左绑定 闭包参数
        def closure7 =closure5.rcurry(2, "Java")
        // 闭包有默认值 , 调用时可以不传入参数
        closure7()

        // 从第 n 个参数开始绑定闭包参数 ,
        // 注意调用了 curry / ncurry / rcurry 方法后 , 之前的默认值就覆盖了
        // 此时第一个参数没有值了
        // 调用时 , 必须传入第一个参数只才可以
        def closure8 =closure5.ncurry(1, "Kotlin")
        // 闭包的第一个默认值被取消 , 此时必须传入第一个参数的值才能执行该闭包
        // 否则报错
        closure8(3)
    }
}

执行结果 :

代码语言:javascript
复制
Accept One Arguments : Hello
Accept One Arguments : Hello
Not Accept Arguments
Not Accept Arguments
1
2
1 : 2
3 : 4
0 : Groovy
1 : Gradle
2 : Java
3 : Kotlin
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、闭包参数绑定
    • 1、闭包参数绑定 curry 函数
      • 2、闭包参数绑定 rcurry 函数
        • 3、闭包参数绑定 ncurry 函数
        • 二、完整代码示例
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档