在Scala中使用重载方法的方法和函数之间的扩展
我想了解为什么eta扩展(§6.26.5)不适用于重载方法.例如,如果我有以下两种方法:
def d1(a: Int,b: Int) {} def r[A,B](delegate: (A,B) ? Unit) {} 我可以做这个: r(d1) 但是,当超载r将不再工作: def r[A,B) ? Unit) {} def r[A,B,C](delegate: (A,C) ? Unit) {} r(d1) // no longer compiles 我必须将方法显式转换为部分应用的函数: r(d1 _) 有没有办法完成以下明确的转换? def r[A,C) ? Unit) {} def d1(a: Int,b: Int) {} def d2(a: Int,b: Int,c: Int) {} r(d1) // only compiles with r(d1 _) r(d2) // only compiles with r(d2 _) 有一些类似的question,但没有完全解释. 解决方法
隐含是正确的术语,该部分在规范中为6.26.2,这必须是重复的问题(或者可以这样想,这是稳定的行为).
链接的问题也解决了预期的类型必须是一个函数. 我会出来一个肢体,说如果超载,适用性被破坏,因为没有预期的类型(6.26.3,臭名昭着).当不重载时,6.26.2适用(eta expansion),因为参数的类型决定了预期的类型.当超载时,arg是特定类型的,没有预期的类型,因此6.26.2不适用;因此,d的任何超载变体都不被认为是适用的.
当您命名不带参数的方法时,可以使用“隐式转换”(所谓的)(如r(d1)).关于eta扩展的段落适用于此.
更多绿色后检查说明… 以下示例表明,在存在超载的情况下,更喜欢应用于eta扩展.当eta扩展不适用时,“空应用”是在6.26.2中尝试的最终内容.换句话说,当超载(在它的表面上是令人困惑和恶劣的)时,通过统一访问原则将f作为f()是很自然的,但是f取为f而不自然或奇怪,除非你很确定功能类型是预期的. scala> object Bar { | def r(f: () => Int) = 1 | def r(i: Int) = 2 | } defined module Bar scala> def f() = 4 f: ()Int scala> Bar.r(f) res4: Int = 2 scala> Bar.r(f _) res5: Int = 1 超载分辨率的候选人通过“形状”进行了预先筛选.形状测试封装了从不使用eta扩展的直觉,因为没有预期类型的??键入.这个例子表明,即使是“表达式进行检查的唯一方法”,也不会使用eta扩展. scala> object Bar { | def bar(f: () => Int) = 1 | def bar(is: Array[Int]) = 2 | } defined object Bar scala> def m() = 7 m: ()Int scala> m _ res0: () => Int = <function0> scala> Bar.bar(m) <console>:10: error: overloaded method value bar with alternatives: (is: Array[Int])Int <and> (f: () => Int)Int cannot be applied to (Int) Bar.bar(m) ^ 任何读这方面的人都会对a related issue with these two conversions感到好奇. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |