2016-11-05 19 views
6

W Scala 2.12 importowanie kontekstu wykonywania global, a następnie posiadanie innego niejawnego kontekstu wykonania zdefiniowanego w zakresie powoduje niejednoznaczne niejawne, podczas gdy w 2.11 działa dobrze.Priorytet Implicit ExecutionContext w Scali 2.12

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

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

kompilator daje błąd:

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] 
         ^

Co jest tego przyczyną i jak go obejść w kodzie?

+1

Odpowiedni commit w scala/scala repo to https://github.com/scala/scala/commit/44953dcb08fc5dd92e423a56bd42bcc32757aaef, a uzasadnieniem zmiany jest https://issues.scala-lang.org/browse/SI-8849 –

+0

Viktor Klang komentuje ten bilet JIRA: "polecam jawnie przekazać ExecutionContext.global lub wprowadzić jego własną, domniemaną wartość val, wskazując w razie potrzeby" –

+0

Jeśli dobrze zrozumiałem problem, w 2.11 faktycznie działa "źle" lub na samym poziomie najmniej niespodziewanie, ponieważ "globalny" jest wybierany w sposób ukryty w zakresie? I 2.12 ujawnia ten potencjalny błąd programowania, czyniąc go niejednoznacznym. Warto wspomnieć o uwagach do wydania i/lub w dokumentacji. – ochrons

Odpowiedz

2

Specyfikacja traktuje rozdzielczość przeciążenia jako ujednoznacznienie wybranych członków klasy. Jednak niejawna rozdzielczość używa statycznej rozdzielczości przeciążania do wyboru między referencjami, które nie są członkami.

Prawdopodobnie po to błędna interpretacja spec, ponieważ zzz jest zdefiniowana w klasie pochodnej od X dużo jak yyy jest:

$ 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] } 
                      ^

Obecnie, trzeba polegać na nazywanie do cienia niejawny z załączając zakres:

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

Albo

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>