Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 隐含的范围_Scala_Scope_Implicit - Fatal编程技术网

Scala 隐含的范围

Scala 隐含的范围,scala,scope,implicit,Scala,Scope,Implicit,作为对我的另一个问题的跟进,请参见代码中的注释/问题: case class Implicit(name: String) def foo(implicit i: Implicit = null) = println(Option(i)) def bar1(implicit i: Implicit) { foo // prints None implicit val i = Implicit("J") // Why is call to foo above affected alth

作为对我的另一个问题的跟进,请参见代码中的注释/问题:

case class Implicit(name: String)

def foo(implicit i: Implicit = null) = println(Option(i))

def bar1(implicit i: Implicit) {
  foo // prints None
  implicit val i = Implicit("J") // Why is call to foo above affected although this line comes after?
  foo // prints Some(Implicit(I))
}

def bar2(implicit i: Implicit) {
  foo // prints None
  implicit val i = null
  implicit val j = Implicit("J")
  foo // prints None // Why? Should raise ambiguous implicits or at least choose j.
}

def bar3(implicit i: Implicit) {
  foo // prints None
  val i = null
  implicit val j = Implicit("J")
  foo // prints Some(Implicit(J)) // Now it works as I expected to work in bar2.
}

def bar4(implicit i: Implicit) { // That's how I expected to see bar1 working. A ugly hack here. 
  foo // prints Some(Implicit(I))
  locally {
    val i = null
    implicit val j = Implicit("J")
    foo // prints Some(Implicit(J))
  }
}

val i = Implicit("I")
bar1(i)
bar2(i)
bar3(i)
bar4(i)

您的代码存在名称阴影。中的规范说明了这一点:

绑定具有一个作用域,在该作用域中,可以使用简单名称访问由单个名称定义的实体。作用域是嵌套的某些内部作用域中的绑定会隐藏同一作用域中优先级较低的绑定以及外部作用域中优先级相同或较低的绑定。

在您的示例中,这意味着

def foo(implicit i: Implicit) = println(Option(i))
我们有以下几种可能性:

  • 隐式参数
    i
    传递给
    foo
    ,因为
    x
    将是一个正向引用:

    scala> def f(implicit i: Implicit) = {foo; implicit val x = Implicit("i")}
    f: (implicit i: Implicit)Unit
    
  • 无法将任何内容传递给
    foo
    ,因为参数
    i
    被本地值
    i
    遮挡,该值具有更高的优先级,但无法调用,因为它是正向引用

    scala> def f(implicit i: Implicit) = {foo; implicit val i = Implicit("i")}
    <console>:11: error: could not find implicit value for parameter i: Implicit
           def f(implicit i: Implicit) = {foo; implicit val i = Implicit("i")}
                                          ^
    

  • 您对
    foo
    的定义已使用隐式参数的默认值声明。这不会改变上述规则中的任何内容,但编译器可以在没有其他值可用时选择默认值。

    有趣!特别是3。(不得具有相同的类型)和4。!为什么
    i
    具有更高的优先级,因为
    Null规则是子类型的优先级始终高于超类型。这就是为什么类型
    A;B
    
    scala> def f(implicit i: Implicit) = {implicit val j = Implicit("i"); foo}
    <console>:11: error: ambiguous implicit values:
     both value i of type Implicit
     and value j of type Implicit
     match expected type Implicit
           def f(implicit i: Implicit) = {implicit val j = Implicit("i"); foo}
                                                                          ^
    
    scala> def f(implicit i: Implicit) = {val i = null; implicit val j = Implicit("i"); foo}
    f: (implicit i: Implicit)Unit
    
    scala> def f(implicit i: Implicit) = {implicit val i = null; implicit val j = Implicit("i"); foo}
    f: (implicit i: Implicit)Unit