6

PartialFunctionクラス コンストラクターでリテラルを使用できないという制限があるようです。

scala> case class X(a: PartialFunction[Any, Any]) { def this() = this({case x => x}) }
<console>:7: error: Implementation restriction: <$anon: Any => Any> requires premature access to class X.
   case class X(a: PartialFunction[Any, Any]) { def this() = this({ case x => x}) }

私の最初の質問は、なぜ部分関数リテラルが「this」にアクセスする必要があるのか​​ということです。私の 2 番目の質問/観察は、Scala REPL で同じコードを再度実行すると REPL がクラッシュするということです。

scala> case class X(a: PartialFunction[Any, Any]) { def this() = this({ case x => x}) }
java.lang.NullPointerException
    at scala.tools.nsc.Global$Run.compileLate(Global.scala:1595)
    at scala.tools.nsc.GlobalSymbolLoaders.compileLate(GlobalSymbolLoaders.scala:29)
    at scala.tools.nsc.symtab.SymbolLoaders$SourcefileLoader.doComplete(SymbolLoaders.scala:369)
    ...

最後に、この問題に対する適切な回避策はありますか?

4

2 に答える 2

7

最初の質問は、この質問のコメント セクションで回答されます

Imm の引用:

匿名クラスは、それを囲むクラスにアクセスできます。コンパイラは、匿名の部分関数が実際には何にもアクセスしていないことを認識していません (これを完全に一般的にチェックするのは非常に困難です)。適切なクラスになるまで、匿名クラスの作成を禁止するだけです。

REPL がクラッシュする理由は良い質問です。おそらく、このコード例で Typesafe にチケットを送信する必要があります。

回避策は非常に簡単です。クラスの外部で無名関数を定義するだけで、コンパイラはあなたが閉じている正確な状態を知ることができます:

object X {
  val Default: PartialFunction[Any, Any] = { case x => x }
}

case class X(a: PartialFunction[Any, Any]) {
  def this() = this(X.Default)
}
于 2015-06-13T20:58:03.333 に答える
1

最初の質問は、この質問のコメント セクションで回答されます。

問題は、コンパイラーがコンストラクターのパラメーター ブロックから何かを持ち上げる方法を知らなかったため、コンパイラーの制限が強すぎることです。

回避策は他の回答に記載されています。これは、コンパイラが他のものに対して行うべきことです。

他の回避策は手動で作成することです:

case class X(a: PartialFunction[Any, Any]) { def this() = this({
    class $anonfun extends runtime.AbstractPartialFunction[Any, Any] {
      override def applyOrElse[A, B >: Any](x: A, default: A => B): B = x match {
        case x => x
        //case _ => default(x) // completeness
      }
      override def isDefinedAt(x: Any) = x match {
        case x => true
        //case _ => false
      }
    }
    new $anonfun()
  })
}

2 番目の質問に対する答えは、2.11.7 で修正されたSI-9170であるということです。

于 2015-06-14T00:10:08.297 に答える