【问题标题】:Groovy .& closure (method pointer operator) vs {} closure - MethodMissingExceptionGroovy .& 闭包(方法指针运算符)与 {} 闭包 - MethodMissingException
【发布时间】:2019-12-05 17:54:20
【问题描述】:

我是 Groovy 的新手,我正在尝试使用闭包和 .& 方法指针运算符。

为了进一步了解 Groovy 的工作原理,我设置了以下示例。

我预计isString 的所有 3 个版本都会返回 true - 但是 isString3 会抛出 MethodMissingException,我不确定我是否理解 isString2isString3 之间的实际区别是什么导致异常。

string = 'foo'
isString = {it instanceof String}
println isString(string) // true

// let's try it a different way
isString2 = {String.isInstance(it)}
println isString2(string) // true

// let's try using .& for fancy FP eta reduction
isString3 = String.&isInstance
println isString3(string) // MethodMissingException

// ^^^ No signature of method: java.lang.String.isInstance()
// is applicable for argument types: 
// (java.lang.String) values: [foo]

// EDIT: Case #4
// what if we try a method we know does not exist?
isNotString = String.&isNotInstance
println isNotString(string) // MethodMissingException
// ^^^ gives the same error!

// EDIT: Case #5
// Maybe I am misunderstanding how the .& operator works - let's try an example

bar = 'bar'
equalsBar = bar.&equals
println equalsBar('bar') // true - same as 'bar'.equals('bar')
println equalsBar('baz') // false - same as 'bar'.equals('baz')
// the .& operator has worked as expected in this case

我尝试在 SO 周围搜索其他答案,但没有真正找到解释我在这里看到的实际差异的答案。

【问题讨论】:

  • def tmp = java.lang.String.&isInstance
  • @DaveNewton 做出这种改变似乎并没有改变我所看到的行为。
  • 这对我来说是零星的,我不知道为什么——为了格式化,我会在答案中显示我的 groovysh 输出。
  • isInstance 来自“类”类,equals 来自对象类。那里可能有一些不同。

标签: groovy closures


【解决方案1】:

(不是答案。)

groovy:000> def tmp = java.lang.String.&isInstance
===> org.codehaus.groovy.runtime.MethodClosure@92031aba
groovy:000> tmp('hi')
===> true

酷。

groovy:000> def tmp2 = String.&isInstance
===> org.codehaus.groovy.runtime.MethodClosure@99643448
groovy:000> tmp2('hi')
No signature of method: groovysh_evaluate.tmp2() is applicable for argument types: (java.lang.String) values: [hi]
Possible solutions: dump(), wait(), run(), run(), find(), any()

Wat...

groovy:000> String
===> class java.lang.String
groovy:000> def tmp = String.&isInstance
===> org.codehaus.groovy.runtime.MethodClosure@4b3e238d
groovy:000> tmp('hi')
===> true

酷。

groovy:000> def tmp2 = String.&isInstance
===> org.codehaus.groovy.runtime.MethodClosure@3fdea076
groovy:000> tmp2('hi')
No signature of method: groovysh_evaluate.tmp2() is applicable for argument types: (java.lang.String) values: [hi]
Possible solutions: dump(), wait(), run(), run(), find(), any()
groovy:000> def wat = String.&isInstance
===> org.codehaus.groovy.runtime.MethodClosure@e3cc658a
groovy:000> wat('hi')
No signature of method: groovysh_evaluate.wat() is applicable for argument types: (java.lang.String) values: [hi]
Possible solutions: wait(), wait(long), wait(long, int), with(groovy.lang.Closure), run(), run()

哎呀。

【讨论】:

  • 如果我使用的是def,有时我会在groovysh 中遇到问题 - 您可以在没有它的情况下重试示例。我认为使用def 的任何内容都仅限于您发出的单个命令,一旦命令运行,def var 就会超出范围。这就是为什么您看到 no signature of ... tmp2() 而不是 no signature of ... isInstance()
  • 如果你已经安装了groovyConsole,你也可以在命令行中使用它,或者你可以尝试使用groovy-playground.appspot.com来做一些不需要安装/配置的东西:)
【解决方案2】:

您遇到的问题是使用String 作为类型和类引起的。在 Java 中,String.class 将是类,而 String 用于类型。 isInstance 方法定义为Class<String>.isInstance(),而.& 尝试将其作为(静态)方法访问为String.isInstance()。因此错误

没有方法签名:java.lang.String.isInstance()

闭包不会寻找java.lang.String.class.isInstance(),这会起作用。我找不到用.&isInstance 真正返回此方法并为String 返回true 的方法。

【讨论】:

    【解决方案3】:

    将我的代码更改为以下作品:

    isString = String.&invokeMethod.curry('isInstance')
    isString('foo') // true
    // ^ calling isString('foo') is equivalent to calling
    // String.invokeMethod('isInstance', 'foo')
    isString.class // CurriedClosure
    isString instanceof Closure // true
    

    我相信试图从 String 类中关闭是导致问题的原因,但我不确定。

    如果有人可以发布详细解释问题的答案,我会很高兴!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-25
      • 2015-02-18
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多