这个问题与我的另一个问题密切相关(可能导致我解决了这个问题),但这个问题有所不同。
how to allow passing in a => AnyRef function and call that function
我一直在玩不同的功能创作,我坦率地在创建type =>的匿名函数时遇到了麻烦。 AnyRef和=>串。我可以创建一个type()=>的函数AnyRef和()=>字符串我想。
示例1 我有以下代码
def debugLazyTest2(msg: => String) : Unit = {
System.out.println(msg)
}
//and client code
val function: () => String = () => {
executed = true
"asdf"+executed+" hi there"
}
log2.debugLazyTest2(function)
但编译错误说:()=>字符串有意义,但随后说"要求:字符串"而不是" required:=>字符串"
这里发生了什么?
示例2为了得到更奇怪,我有这个代码编译而上面没有编译
def debugLazyTest(msg: => AnyRef) : Unit = {
System.out.println(msg.toString)
}
//and client code which compiles!!!!
val function: () => AnyRef = () => {
executed = true
"asdf"+executed+" hi there"
}
log2.debugLazyTest(function)
这段代码编译虽然它没有按照我想要的方式工作,因为在调用toString之前,库似乎无法调用该函数(这是在我的另一个线程中并且是一个单独的问题)。
关于这里发生了什么的任何想法?
感谢, 迪安
答案 0 :(得分:3)
请考虑以下代码:
scala> def test(x: String) = debugLazyTest2(x)
test: (x: String)Unit
如果我们然后运行(在Scala 2.11.2中):
:javap test
修剪一下生成的输出,我们看到以下内容:
public void test(java.lang.String);
flags: ACC_PUBLIC
Code:
stack=4, locals=2, args_size=2
0: getstatic #19 // Field .MODULE$:L;
3: new #21 // class $anonfun$test$1
6: dup
7: aload_1
8: invokespecial #23 // Method $anonfun$test$1."<init>":(Ljava/lang/String;)V
11: invokevirtual #27 // Method .debugLazyTest2:(Lscala/Function0;)V
14: return
LocalVariableTable:
Start Length Slot Name Signature
0 15 0 this L;
0 15 1 x Ljava/lang/String;
LineNumberTable:
line 8: 0
然后我们考虑debugLazyTest2
的签名:
public void debugLazyTest2(scala.Function0<java.lang.String>);
关键是:
3: new #21 // class $anonfun$test$1
如果我正确阅读代码,我们将实例化类$anonfun$test$1
的新实例 - 并将新的匿名Function0[String]
传递给debugLazyTest2
。这使我们的test
方法等效于以下内容:
def test(x: String) = debugLazyTest2(new Function0[String] {
def apply(): String = x
})
当我们考虑将Function0[String]
的实例传递给debugLazyTest2
进行相同的转换时,我们得到:
debugLazyTest2(function)
变为:
debugLazyTest2(new Function0[String] {
def apply(): Function0[String] = function
})
当然不会编译,因为apply(): Function0[String]
与所需类型apply(): String
不匹配(因此错误消息)。
实际上调用函数而不是返回它的工作原理:
debugLazyTest2(function())
变为:
debugLazyTest2(new Function0[String] {
def apply(): String = function()
})
答案 1 :(得分:3)
如果你这样写它会起作用:
log2.debugLazyTest2(function())
msg是一个名字参数,而不是一个函数。您必须传入String类型的表达式(或第二个示例中的AnyRef)
第二个例子编译因为()=&gt;你传入的AnyRef实际上也是一个AnyRef,因为一个函数是一个AnyRef。但是,它是打印的函数本身,而不是执行它的结果。