Groovy中的功能样式计数器

 手机用户2502906401 发布于 2023-02-09 13:17

我是函数式编程概念的新手,正在观看Neil Ford在youtube上的演示.在那里,他谈到了一个计数器来演示一段代码而不使用全局状态(在20:04).来自Java世界,我很难理解这里的概念以及计数器如何递增.以下是相关代码

def makeCounter() {
    def very_local_variable = 0;
    return {very_local_variable += 1}
}

c1 = makeCounter()
c1()
c1()
c1()

c2 = makeCounter()
println "C1 = ${c1()}, C2 = ${c2()}"

他继续说C1 = 4,将打印C2 = 1.这是怎么发生的?我确信我在这里缺乏理解可能源于Groovy如何工作的概念性失败,或者可能在Groovy,Scala等函数式语言中存在一些通用性.方法中的局部变量是否保持其状态,直到再次调用该函数为止分配给另一个变量?(谷歌搜索与"功能计数器groovy | scala"没有带来任何结果)

1 个回答
  • 我不知道为什么这个问题没有答案,但它可能至少应该为未来的访问者提供一个答案.

    你上面写的是一个简单的闭包例子.闭包是一种与语言无关的想法,根本不依赖于Groovy.您可以一直使用它们,例如在JavaScript中.

    闭包本质上是函数或引用环境函数或引用.

    在你的例子中,每次调用makeCounter引入一个新的本地very_local_variable,我认为很清楚.你在该函数的第二行中所做的是返回一个{ .. }不带参数的闭包(语法)并返回以1递增的局部变量.闭包可以访问该变量,因为它存在(它是引用环境的一部分)).

    每次调用makeCounter都会创建一个新的局部变量并返回一个新的闭包,因此每个闭包都在自己的局部变量/环境中运行.

    实际上,如果你来自爪哇岛,那对你来说应该不是那么新鲜.您有匿名类,可以访问最终变量,例如

    Runnable makeCounter() {
      final int[] very_local_variable = {0};
      return new Runnable() {
          @Override
          public void run() {
              very_local_variable[0] += 1;
          }
      };
    }
    
    
    Runnable c1 = makeCounter();
    
    c1.run();
    c1.run();
    c1.run();
    

    将局部变量声明为数组,将其作为Runnable仿函数返回等等......这一切都来自Java的设计和限制,但实际上它非常接近您的代码.Java 8更加接近差距:

    Runnable makeCounter() {
        int[] very_local_var = {0};
        return () -> { very_local_variable[0] += 1; };
    }
    

    2023-02-09 13:18 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有