What is scala experimental virtual pattern matching?

+43
scala pattern-matching
Dec 16 '11 at 11:59
source share
2 answers

A "virtualized" template is a rewrite of an existing connector. The motivation for this was to support pattern matching virtualization for non-2.10 polymorphic embedded DSLs .

As Julian says in the comments below: it is very similar to how compilations are compiled: instead of directly generating code, they translate to foreach , map , filter , etc. The sequence of patterns can be translated into a series of method calls that DSL can overwrite. The default implementation will take into account the current semantics, and the task is to make it as effective as the current one. Adriaan seems very close to this goal. A β€œvirtualized” implementation is simpler and corrects several errors in the current implementation.

"Polymorphic embedded DSL" is the idea that you can write programs in scala that should not run on the JVM. That is, scalac will output output that describes what the program does. This can then be recompiled against a specific architecture. Such things were discussed at ScalaDays 2011 .

This entry will eventually become the standard scala template template. The old template template was (as I understand it) unattainable.

+32
Dec 16 '11 at 13:35
source share

Unfortunately, the (only) existing answer is low on juicy bits, and comment links are broken. So let me try adding some juice here, because if there is no other reason, my own link, when I actually decide to do something with it in the future, seeing that this answer is at the top of every google search that I I do.

A virtualized pattern pattern, as already mentioned, is a rewrite of how the Scala compiler handles pattern matching. It served many purposes, and part of the "virtualization" meant that it was part of Scala's virtualized effort. This effort is a bit opposed to macros: it takes things that are β€œrun” at compile time, and then move around to run time.

For example, given the correct definition in scope, do the following:

 if (false) 1 else 2 

instead of being compiled into bytecodes of branches and literals, or even optimized for the literal "2", it is actually compiled as the following statement:

 __ifThenElse(false, 1, 2) 

See the scala virtualized wiki for more information and some examples of what this might be useful for.

I said, however, that rewriting template templates served many purposes. Another important goal was to turn the spaghetti code, which was an old template, complete or special and corner cases and errors, into something that could be reasoned, expanded and improved more easily. So many problems were fixed in this rewriting that people simply looked at a list of problems that used sample code for questions related to the template and noted that the problems were β€œfixed” when they worked. It has new bugs, but on a much smaller scale.

Now there is very little information about how the new template layout works, but basically it translates into several method calls that are "implemented" in the compiler with the Option monad. Then it goes into the optimization phase, which creates the optimal bytecode.

You can enter your own matches, although it is locked behind the -Xexperimental flag. Try the following code copied from the Scala test suite, with and without this flag:

 trait Intf { type Rep[+T] type M[+T] = Rep[Maybe[T]] val __match: Matcher abstract class Matcher { // runs the matcher on the given input def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U] def zero: M[Nothing] def one[T](x: Rep[T]): M[T] def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T] def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] // used for isDefinedAt } abstract class Maybe[+A] { def flatMap[B](f: Rep[A] => M[B]): M[B] def orElse[B >: A](alternative: => M[B]): M[B] } implicit def proxyMaybe[A](m: M[A]): Maybe[A] implicit def repInt(x: Int): Rep[Int] implicit def repBoolean(x: Boolean): Rep[Boolean] implicit def repString(x: String): Rep[String] def test = 7 match { case 5 => "foo" case _ => "bar" } } trait Impl extends Intf { type Rep[+T] = String object __match extends Matcher { def runOrElse[T, U](in: Rep[T])(matcher: Rep[T] => M[U]): Rep[U] = ("runOrElse("+ in +", ?" + matcher("?") + ")") def zero: M[Nothing] = "zero" def one[T](x: Rep[T]): M[T] = "one("+x.toString+")" def guard[T](cond: Rep[Boolean], then: => Rep[T]): M[T] = "guard("+cond+","+then+")" def isSuccess[T, U](x: Rep[T])(f: Rep[T] => M[U]): Rep[Boolean] = ("isSuccess("+x+", ?" + f("?") + ")") } implicit def proxyMaybe[A](m: M[A]): Maybe[A] = new Maybe[A] { def flatMap[B](f: Rep[A] => M[B]): M[B] = m + ".flatMap(? =>"+ f("?") +")" def orElse[B >: A](alternative: => M[B]): M[B] = m + ".orElse("+ alternative +")" } def repInt(x: Int): Rep[Int] = x.toString def repBoolean(x: Boolean): Rep[Boolean] = x.toString def repString(x: String): Rep[String] = x } object Test extends Impl with Intf with App { println(test) } 

The result without a flag is what you expect:

 scala> Test.main(null) bar 

With -Xexperimental , however, compilation of an alternative "engine" correspondence:

 scala> Test.main(null) runOrElse(7, ?guard(false,?).flatMap(? =>one(foo)).orElse(one(bar))) 

See also additional scalability information for PatternMatching and MatchMonadInterface .

Disclaimer: there was an extraction above and was performed from the Scala version on the main branch after 2.10.0, so there may be differences. Unfortunately, I lack a clean environment of 2.10.0 or 2.10.1 to test it.

+8
May 13, '13 at 16:19
source share



All Articles