Scala:Function0 vs by-name参数
任何人都可以就名字参数=>给出明确的答案. T和Function0参数()=>
Scala编译器将T转换为另一个?我知道它们不一样,但差异非常微妙,因为它们可以在许多情况下互换使用.
示例:如果我定义 def someFunction: Int = 2 def f(x: => Int): Unit = println(x) 然后我可以成功打电话 f(2) f(someFunction) 怎么是()=>在=>中可接受的替代品诠释? 更一般地说,是()=>是一个普遍接受的替代名称=> T参数? 另外,如果我在下面的推理中错了,请纠正我:=> T绝不是()=>的可接受替代品. T因为第一个是值类型(T),另一个是函数类型.也就是说,如果我有def f(x :()=> Int),我将永远无法传递Int或惰性Int(因为没有惰性类型,所以无论如何都没有意义). 解决方法
好的,这是完全崩溃.
def value: Int = ??? def method(): Int = ??? def f1(f: () => Int) = ??? def f2(f: => Int) = ??? f1(value) // fails f1(method) // works f2(value) // works f2(method) // works with a warning "empty-paren method accessed as parameterless" >
这个失败是因为f1期望一个Unit => Int函数,但是给出了Int值. >
这个有效,因为f1期待一个函数,并给出一个方法.这是区别:方法不是Scala中的值;它不能独立存在,并且是(class,trait,object等)中定义的上下文的属性.功能是一个价值;它可以保存在一个集合中,作为另一个函数中的参数,从函数等返回.当编译器期望一个函数并给出一个方法时,它执行eta扩展.给定一个例如f:(a:Int,b:Int)=> Int,eta扩展是在保留签名的同时创建另一层的过程,因此它变为(a:Int,b:Int)=> f(a,b).这种技术很有用,因为我们可以将方法转化为函数.给定一些方法def f(a:Int):Int = ???,我们可以执行eta-expansion来创建Int =>类型的函数. Int out of it:(a:Int)=> F A).如果你有兴趣的话,我前段时间写了一篇关于这个的blog post. >
工作没有意外,但要注意每次在函数体中使用时访问传递的值这一事实. >
工作,但警告我们正在调用一个用空括号定义的方法,不使用括号.好的做法是使用没有括号的方法(例如f),当它们只是表示一个值时,但是每次访问时都会重新计算一个值,例如: numberOfUpvotes,并且当执行某种副作用时使用具有空括号的方法(例如f()),因此该方法不是幂等的,例如,createSnapshot()(同样,这不应该存在于纯函数代码中). 忠告:不要用什么替代什么来阻碍你的思想.不要使用替换品.如果某些东西需要一个功能,请提供一个功能.如果需要值,请提供值.如果定义了没有parens的方法,则在没有parens的情况下调用它.如果它有parens,请用parens调用它. 如果你需要从一个方法转到另一个函数并且编译器期望一个函数,那么eta-expansion将自动发生.如果它不期望一个功能,你需要手动完成. def f(): Int = ??? val a = f // no function context; a is a string val b: () => Int = f // b is a function Unit => Int val c = f2 _ // c is a function Unit => Int 最后一种情况是部分应用的功能.我觉得我现在走得太宽了所以我会在这里停下来.我希望这有帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |