Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.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 - Fatal编程技术网

Scala 斯卡拉虫?延迟与隐含

Scala 斯卡拉虫?延迟与隐含,scala,Scala,我发现使用和定义隐式值的行为(scala 2.9.1)非常奇怪,我想知道是否有人能解释它,或者这是scala的错误 我创建了一个独立的示例: object AnnoyingObjectForNoPurpose { trait Printer[T] { def doPrint(v: T): Unit } def print[T : Printer](v: T) = implicitly[Printer[T]].doPrint(v) trait DelayedRunn

我发现使用和定义隐式值的行为(scala 2.9.1)非常奇怪,我想知道是否有人能解释它,或者这是scala的错误

我创建了一个独立的示例:

object AnnoyingObjectForNoPurpose {

  trait Printer[T] {
    def doPrint(v: T): Unit
  }

  def print[T : Printer](v: T) = implicitly[Printer[T]].doPrint(v)


  trait DelayedRunner extends DelayedInit {
    def delayedInit(x: => Unit){ x }
  }

  // this works, as it should
  object Normal extends DelayedRunner {
      implicit val imp = new Printer[Int] {
        def doPrint(v: Int) = println(v + " should work")
      }

      print(343)
  }

  // this compiles, but it shouldn't
  // and won't run, cause the implicit is still null
  object FalsePositive extends DelayedRunner {

      print(123)

      implicit val imp = new Printer[Int] {
        def doPrint(v: Int) = println(v + " should not compile")
      }
  }

  def main(args: Array[String]) {
    implicit val imp = new Printer[Int] {
      def doPrint(v: Int) = println(v + " should work")
    }

    print(44)
    // print(33.0) // correctly doesn't work 

    Normal // force it to run
    FalsePositive // force this to run too 
  }
}

这和我写的是一样的错误:

object Foo {
   println(x)
   val x = 5
}

这不是虫子。构造函数沿着对象体向下流动,并按顺序进行<代码>延迟不是原因。这就是为什么在使用val/vars时需要小心,并确保它们首先初始化。这也是人们使用lazy val解决初始化顺序问题的原因。

假设您将
delayInit
的定义更改为no op,即

def delayedInit(x: => Unit) {  }
然后在你的主要方法中做一些类似的事情

println("FP.imp: " + FalsePositive.imp)
正如预期的那样,它将打印
FP.imp:null
,但练习的真正目的是说明定义
假阳性
主体的块的行为类似于常规类主体,而不是函数主体。它在看到
val
时定义公共成员,而不是局部变量

如果像下面这样向
烦扰对象添加了一个方法,它将无法编译,因为
打印
的隐式要求没有得到满足

def fails {
  print(321)
  implicit val cantSeeIt = new Printer[Int] {
    def doPrint(v: Int) = println(v + " doesn't compile")
  }
}
但是,如果您按照相同的原则定义了一个类,它将编译,但在初始化时会在运行时失败,就像您的
false-positive
示例一样

class Fine {
  print(321)
  implicit val willBeNull = new Printer[Int] {
    def doPrint(v: Int) = println(v + " compiles, but fails")
  }
}
需要明确的是,
Fine
的编译行为与
隐式
的存在无关。类/对象初始值设定项非常乐意使用引用未定义的
val
s的
val
初始值设定项进行编译

object Boring {
  val b = a
  val a = 1
  println("a=%s b=%s".format(a, b))
}
Boring
编译得很好,当引用它时,它会打印
a=1 b=0

您的问题似乎可以归结为“从
DelayedInit
派生的类/对象的主体是否应该像编译类主体或函数块一样进行编译?”


看起来奥德斯基选择了前者,但你希望是后者。

我觉得很困惑,你在def print(第7行)中重用T作为标识符,这导致了一个问题,
隐式[Printer[T]]
是打印机的隐式打印机吗?不同的标识符是否有助于避免混淆?@userunknown我不太清楚你的意思,或者更简单的书写方式?你能更具体地回答你的问题吗?你说“这是编译,但不应该”,但这是一个陈述,不是一个问题。你的问题是什么?