gpt4 book ai didi

groovy - 使用 kwargs 和 varargs 定义 Groovy 闭包

转载 作者:行者123 更新时间:2023-12-04 03:11:02 24 4
gpt4 key购买 nike

我遇到了让我难过的 Groovy 函数和闭包之间的不一致。

我可以定义一个带有签名 def foo(Map kwargs=[:], ... varargs){...} 的函数,它几乎完全符合我的预期。它几乎需要我给出的每一个命名和未命名的参数。它也不需要任何参数并且可以正常工作。

我找不到类似的方法来定义具有相同签名的闭包。作为快速演示,当我运行以下四行时:

def foo(Map kwargs=[:], ...args ){"kwargs=${kwargs.toString()} args=${args.toString()}"}
def bar = { Map kwargs=[:], ...args -> "kwargs=${kwargs.toString()} args=${args.toString()}"}
println foo(1:1,2:2)
println bar(1:1,2:2)

我得到以下输出:

> groovy test.groovy
kwargs=[1:1, 2:2] args=[]
Caught: groovy.lang.MissingMethodException: No signature of method: test$_run_closure1.call() is applicable for argument types: (java.util.LinkedHashMap) values: [[1:1, 2:2]]
Possible solutions: any(), any(), doCall([Ljava.lang.Object;), any(groovy.lang.Closure), each(groovy.lang.Closure), any(groovy.lang.Closure) groovy.lang.MissingMethodException: No signature of method: test$_run_closure1.call() is applicable for argument types: (java.util.LinkedHashMap) values: [[1:1, 2:2]]
Possible solutions: any(), any(), doCall([Ljava.lang.Object;), any(groovy.lang.Closure), each(groovy.lang.Closure), any(groovy.lang.Closure)
at test.run(test.groovy:4)

运行 Groovy 版本:1.8.6 JVM:1.8.0_131 供应商:Oracle Corporation 操作系统:Linux

我想写一个闭包,它可以接受任意数量的命名或未命名参数,包括根本没有参数。这可能吗?

最佳答案

调查

我试了一下你的例子,我发现了这种情况下发生了什么。

def bar = { Map kwargs = [:], ... args -> "kwargs=${kwargs.toString()} args=${args.toString()}" }
bar.class.methods.findAll { it.name == 'doCall' }.each { println it }

这是您定义的闭包,这是 println 的输出(我们遍历此匿名类中定义的所有方法,并仅打印名称为 doCall 的方法>):

public java.lang.Object cls$_run_closure1.doCall(java.lang.Object[])
public java.lang.Object cls$_run_closure1.doCall(java.util.Map,java.lang.Object[])

这里我们只有两个可能的签名来调用闭包——我们缺少一个带有单个 java.util.Map 参数的签名来满足您的期望。

解决方案

如果我们做一个小改动 - 将默认值应用于 ...args 数组参数,例如:

def bar2 = { Map kwargs = [:], ... args = [] -> "kwargs=${kwargs.toString()} args=${args.toString()}" }
bar2.class.methods.findAll { it.name == 'doCall' }.each { println it }

然后这是println的输出:

public java.lang.Object cls$_run_closure4.doCall(java.util.Map)
public java.lang.Object cls$_run_closure4.doCall(java.util.Map,java.lang.Object[])
public java.lang.Object cls$_run_closure4.doCall()

如您所见,有一个带有单个 java.util.Map 的签名,您可以按预期调用此 bar2 闭包:

bar2(1:1,2:2)

kwargs=[1:1, 2:2] args=[]

bar2(1:1,2:2,3,4)

kwargs=[1:1, 2:2] args=[3, 4]

哦,顺便说一句 - 我已经用 Groovy 2.4.8 测试过它,我没有任何旧版本可以用来测试它。如果它也适用于 1.8.x,请告诉我们。

我必须承认这是一个非常有趣的案例。我也很好奇这是一个错误还是为 groovy 的闭包设计的正确行为。也许具有深入 groovy 内部知识的人可以给我们提示 :)

关于groovy - 使用 kwargs 和 varargs 定义 Groovy 闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45293901/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com