scala – 关于call-by-name和0-arity函数之间差异的一些问题
这里有一些讨论,但我有一些具体的问题,我无法找到答案.因此,通过按名称呼叫,我的意思是=> T型,并且通过0-arity函数我的意思是()=> ?
我理解(我认为)概念上的差异,但可能我错过了一些东西,因为我仍然有很多问题: >为什么我们总是使用=> T的概念,如果我们总能使用()=> T’ 解决方法
1)使用它更方便,特别是在DSL中:
def printAndGet[T](f: => T) = { val res = f println(res + " printed") res } scala> :paste // Entering paste mode (ctrl-D to finish) val k = printAndGet { val a = 5 5 * a } // Exiting paste mode,now interpreting. 25 printed k: Int = 25 2)=> T只能是方法或函数的参数.实际上=> T和()=> T不可互换: scala> def aaa(f: => String) = f aaa: (f: => String)String scala> val a: Function1[() => String,String] = aaa _ <console>:8: error: type mismatch; found : (=> String) => String required: (() => String) => String val a: Function1[() => String,String] = aaa _ ^ 感谢@ som-snytt,发现这个: scala> object O { def f(i: Int) = i; def f(i: => Int) = i + 1 } defined object O scala> O.f(5) res12: Int = 5 scala> O.f(5: (=> Int)) <console>:1: error: no by-name parameter type allowed here O.f(5: (=> Int)) ^ 即使这个应该工作,如果它编译 – 但它没有(scala 2.11.2,2.11.5 REPL只是崩溃): scala> val k: (=> Int) => Int = O.f _ k: (=> Int) => Int = <function1> scala> k(5) //should be 6 res18: Int = 5 //WTF? 最后一个看起来像个bug 3)不完全是,如果你想要相同,只需转换=> T into()=> T: scala> def aaa(f: => String) = {f _} aaa: (f: => String)() => String 字节码也可能不同.例如,编译器更可能内联代码来自=> T没有为它生成lambda.所以,关键的区别是()=> T实际上是一个对象(一等公民),=> T不是. 4)参见1,但有时您可能需要确保用户知道计算可能会延迟 – ()=> T更好. 5)它是类型签名的一部分,只需看看以下的eta扩展: scala> def aaa(f: => String) = {f} aaa: (f: => String)String scala> aaa _ //convert method into a function res7: (=> String) => String = <function1> scala> val a: ( => String) => String = aaa _ a: (=> String) => String = <function1> 但是scala不承认它是独立类型: scala> val a: Function1[( => String),String] = aaa _ <console>:1: error: no by-name parameter type allowed here val a: Function1[( => String),String] = aaa _ ^ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |