加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

在Scala中使用重载方法的方法和函数之间的扩展

发布时间:2020-12-16 09:11:36 所属栏目:安全 来源:网络整理
导读:我想了解为什么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) ? Uni
我想了解为什么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的任何超载变体都不被认为是适用的.

From 6.26.3 Overloading Resolution

Otherwise,let S 1,. . .,S m be the vector of types obtained by
typing each argument with an undefined expected type.

当您命名不带参数的方法时,可以使用“隐式转换”(所谓的)(如r(d1)).关于eta扩展的段落适用于此.

6.26.2 Method Conversions

The following four implicit conversions can be applied to methods
which are not applied to some argument list.

Evaluation. A parameterless method m of type => T is always converted
to type T by evaluating the expression to which m is bound.

Implicit Application. If the method takes only implicit parameters,
implicit argu- ments are passed following the rules of §7.2.

Eta Expansion. Otherwise,if the method is not a constructor,and the
expected type pt is a function type (Ts ) ? T,eta-expansion
(§6.26.5) is performed on the expression e.

Empty Application. Otherwise,if e has method type ()T,it is
implicitly applied to the empty argument list,yielding e()

更多绿色后检查说明…

以下示例表明,在存在超载的情况下,更喜欢应用于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感到好奇.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读