简体   繁体   English

Scala 2.12中的隐式ExecutionContext优先级

[英]Implicit ExecutionContext priority in Scala 2.12

In Scala 2.12 importing the global execution context and then having another implicit execution context defined in the scope results in an ambiguous implicit, while in 2.11 it works just fine. 在Scala 2.12中导入global执行上下文然后在作用域中定义了另一个隐式执行上下文导致模糊隐式,而在2.11中它可以正常工作。

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global

class A(implicit ec: ExecutionContext) {
  x = implicitly[ExecutionContext]
}

Compiler gives error: 编译器给出错误:

error: ambiguous implicit values:
 both lazy value global in object Implicits of type => scala.concurrent.ExecutionContext
 and value ec in class A of type scala.concurrent.ExecutionContext
 match expected type scala.concurrent.ExecutionContext
       val x = implicitly[ExecutionContext]
                         ^

What is the cause of this and how to work around it in code? 这是什么原因以及如何在代码中解决它?

The spec treats overload resolution as the disambiguation of a selection of members of a class. 规范将重载决策视为选择类成员的消歧。 But implicit resolution uses static overload resolution to choose between references which are not members. 但隐式解析使用静态重载决策来选择不是成员的引用。

Arguably, the following is a misinterpretation of the spec, since zzz is defined in a class derived from X much as yyy is: 可以说,以下是对规范的误解,因为zzz是在一个派生自X的类中定义的,因为yyy是:

$ scala
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.

scala> import concurrent._, ExecutionContext.global
import concurrent._
import ExecutionContext.global

scala> trait X { implicit val xxx: ExecutionContext = global }
defined trait X

scala> class Y extends X { implicit val yyy: ExecutionContext = global ; def f = implicitly[ExecutionContext] }
defined class Y

scala> class Z extends X { def f(implicit zzz: ExecutionContext) = implicitly[ExecutionContext] }
<console>:16: error: ambiguous implicit values:
 both value xxx in trait X of type => scala.concurrent.ExecutionContext
 and value zzz of type scala.concurrent.ExecutionContext
 match expected type scala.concurrent.ExecutionContext
       class Z extends X { def f(implicit zzz: ExecutionContext) = implicitly[ExecutionContext] }
                                                                             ^

Currently, you must rely on naming to shadow the implicit from enclosing scope: 目前,您必须依靠命名来隐藏隐藏的封闭范围:

scala> class Z extends X { def f(implicit xxx: ExecutionContext) = implicitly[ExecutionContext] }
defined class Z

Or, 要么,

scala> :pa
// Entering paste mode (ctrl-D to finish)

package object p { import concurrent._ ; implicit val xxx: ExecutionContext = ExecutionContext.global }
package p { import concurrent._ ;
  class P { def f(implicit xxx: ExecutionContext) = implicitly[ExecutionContext]
            def g = implicitly[ExecutionContext] }
}

// Exiting paste mode, now interpreting.


scala> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM