Cannot put PartialFunction in constructor of scala class

There seems to be a limitation in which you cannot use PartialFunction literals in class constructors:

 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}) } 

My first question is why a partial function private literal needs access to "this". My second question / observation is that in Scala REPL, running the same code again causes a REPL error:

 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) ... 

And finally, is there a good way to solve this problem?

+6
source share
2 answers

Your first question is answered in the comments section on this issue.

Quoting Imm:

Anonymous classes have access to their closing class. The compiler does not know that your anonymous partial function does not actually have access to anything (and it would be very difficult to verify this in full generality); it simply prohibits creating any anonymous classes until you get to the corresponding class.

Why is this a REPL crash - a good question, you should probably send a ticket to Typesafe with this code example.

The workaround is pretty simple, just define an anonymous function outside the class so that the compiler knows the exact state you are closing:

 object X { val Default: PartialFunction[Any, Any] = { case x => x } } case class X(a: PartialFunction[Any, Any]) { def this() = this(X.Default) } 
+7
source

Your first question is answered in the comments section of this question .

The problem is that the compiler is too restrictive because it did not know how to extract material from the constructor parameter block.

A workaround is given in another answer that the compiler should do with this other stuff.

Another solution is a manual design:

 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() }) } 

The answer to your second question is that it is SI-9170 , fixed for 2.11.7.

+1
source

Source: https://habr.com/ru/post/989072/


All Articles