Scala macro: rewrite partial function into match - scala

I would like to rewrite partial function into match expression.
//macro and impl
def pfRewrite(pf: PartialFunction[Int, Int]) = macro ResponderImpl.pfRewriteImpl
def pfRewriteImpl(c: Context)(pf: c.Expr[PartialFunction[Int, Int]]) = {
import c.universe._
val cas = pf.tree.collect {
case x: DefDef if x.name.decoded == "applyOrElse" =>
x.collect {
case cq"$x => $y" => cq"""$x => $y"""
}
}.flatten
val sVal = newTermName("someVal")
val rewrite = q"""
$sVal match {
case ..$cas
}
"""
c.Expr(rewrite)
}
In code i got a PartialFunction and take a cases from applyOrElse method, next i create a match expression for "someVal". This value from code:
//test
def test {
val someVal = 10
pfRewrite {
case 1 => 10
case _ => 100
}
}
But i got errors:
[error] found : Int(10)
[error] required: Nothing
[error] case 1 => 10
[error] ^
and etc.
It possible rewrite partial function call into match ?

Typically these kinds of awkward error messages stem from mixing typed and untyped trees (for more details take a look at Scala macros: What is the difference between typed (aka typechecked) an untyped Trees). Therefore, until we've fixed the situation, it's good practice to do resetLocalAttrs on typed trees that you plan to mix with untyped ones.
This case is not an exception. Using c.resetLocalAttrs(pf.tree) instead of just pf.tree reveals the real problem with the macro expansion:
12:57 ~/Projects/Master/sandbox (master)$ scalac Test.scala
Test.scala:5: error: not found: value default
Macros.pfRewrite {
^
If we enable -Xprint:typer, which is one of the ways to see macro expansions (along with -Ymacro-debug-lite and -Ymacro-debug-verbose), then we'll see what's going on:
[[syntax trees at end of typer]] // Test.scala
package <empty> {
object Test extends AnyRef with App {
def <init>(): Test.type = {
Test.super.<init>();
()
};
def test: Unit = {
val someVal: Int = 10;
{
someVal match {
case 1 => 10
case _ => 100
case (defaultCase$ # _) => <default: error>.apply(<x1: error>)
};
()
}
}
}
}
It looks like partial function synthesis also adds a default case that we can't reuse as-is, as it refers to some synthetic variables defined in the synthesized class.

Related

Get Name of Reified Function Using Scala Macros

I would like to pattern match certain function and other variable references inside a macro traversing over a Tree. Currently, I am matching based on symbol.fullname like this:
tree match {
case "$f($x)" if f.symbol != null
&& f.symbol.fullName == "_root_.mypackage.MyClass.myfunc" =>
...
case "$f($x)" if f.symbol != null
&& f.symbol.fullName == "_root_.mypackage.MyClass2.myfunc2" =>
...
case ...
}
However, I would like to additionally check during compilation of this macro that those functions actually exists, e.g. instead of having String, I would like to directly use references, such that the IDE can tell me whether I had a typo in the 'myfunc' name. I was thinking of using using reify, but I am not sure whether that works.
Now lets assume i was looking for println instead of MyClass.myfunc. The first problem I encountered is that you cannot reify(println) or any other function reference directly, because in Scala there are no function references, so you have to write reify(println _) or more specificly in this case reify(println (_: String)) to select what println function we want to call. With the following code I collected all symbols that are inside the expression, but sadly only Predef (from Predef.println) is found but not println itself:
println(reify( println (_:String) ).tree
.collect { case x if x.symbol != null => x.symbol.fullName } )
// List(<none>, <none>, <none>, scala.Predef, <none>, <none>, scala.Predef, <none>, <none>, scala.Predef)
Any ideas for getting the name of something in scala (currently using 2.12)?
reify(println) compiles.
How do you imagine symbol of function println (_:String)? Where is this function defined? In Predef two methods are defined:
def println(): Unit
def println(x: Any): Unit
Try
val mirror = scala.reflect.runtime.universe.runtimeMirror(this.getClass.getClassLoader) // at runtime
// val mirror = c.mirror // at compile time
mirror.staticClass("mypackage.MyClass").typeSignature.decl(TermName("myfunc"))
// method myfunc
or
typeOf[MyClass].decl(TermName("myfunc"))
// method myfunc
for MyClass#myfunc
definitions.PredefModule.typeSignature.decl(TermName("println")).alternatives
// List(method println, method println)
for both println
definitions.PredefModule.typeSignature.decl(TermName("println")).alternatives
.filter(_.asMethod.paramLists.map(_.map(_.typeSignature)) == List(List(definitions.AnyTpe)))
// List(method println)
for println(Any):Unit.
For example
def foo(x: Any): Unit = macro impl
def impl(c: blackbox.Context)(x: c.Tree): c.Tree = {
import c.universe._
val printlnSymb = definitions.PredefModule.typeSignature.decl(TermName("println")).alternatives
.filter(_.asMethod.paramLists.map(_.map(_.typeSignature)) == List(List(definitions.AnyTpe)))
.head
x match {
case q"$f($x)" if f.symbol == printlnSymb =>
println("test")
}
q"()"
}
foo(println(1)) //Warning:scalac: test
reify( println (_:String) ).tree.collect { ... produces only List(<none>, <none>, <none>, scala.Predef, <none>, <none>, scala.Predef, <none>, <none>, scala.Predef) because tree reify( println (_:String) ).tree is not typechecked (for typechecked tree it produces List($anonfun, x$1, java.lang.String, scala.Predef.println, scala.Predef.println, scala.Predef, x$1, java.lang.String)).
So another option is to do c.typecheck
def impl(c: blackbox.Context)(x: c.Tree): c.Tree = {
import c.universe._
val printlnSymb = (c.typecheck(q"println(_:Any)", silent = false) match {
case q"($_) => $p($_)" => p
}).symbol
//val printlnSymb = (c.typecheck(reify { println(_:Any) }.tree, silent = false) match {
// case q"($_) => $p($_)" => p
//}).symbol
x match {
case q"$f($x)" if f.symbol == printlnSymb =>
println("test")
}
q"()"
}
To get the symbols of a reified expressions, the tree of the expressions needs another explicitly pass through typechecking, so the following code works:
val mySym1 = c.typecheck(reify(mypackage.myfunction1 _).tree) match {
case q"{(..$_) => $f(..$_)}" => f.symbol
}
val mySym2 = c.typecheck(reify(mypackage.myfunction2 _).tree) match {
case q"{(..$_) => $f(..$_)}" => f.symbol
}
println(mySym.fullName)
// _root_.mypackage.myfunction1
Then you can match based on the symbol:
tree match {
case "$f($x)" if f.symbol != null => f.symbol match {
case x if x == mySym1 => ...
case x if x == mySym2 => ...
case ...
}
case ...
}
There is actually a function called def symbolOf[X]: TypeSymbol that can be used to get a TypeSymbol from a Type. But this only works for TypeSymbols, not TermSymbols, so we cannot do this on functions.
However, if this is our own function, we can replace the definition from def myfunc(): Int = ... with object myfunc { def apply(): Int = ... }. As each object has its own type (called myfunc.type) we can now do the following
package main
object myfunc { def apply(): Int = 1 }
object myfunc2 { def apply(): Int = 1 }
...
tree match {
case "$f.apply($x)" if f.symbol == symbolOf[myfunc.type] => ...
case "$f.apply($x)" if f.symbol == symbolOf[myfunc2.type] => ...
case ...
}

How to pattern match types in Scala macros?

I have a method in my project with macros (whitebox), trying to verify and extract type arguments from a return type of a MethodSymbol.
Here is the code (placed inside some class with import c.universe._):
private object ImplMethod {
def apply(m: MethodSymbol): ImplMethod = {
println(m.returnType)
val respType = m.returnType match {
case tq"scala.concurrent.Future[scala.util.Either[String, ${resp}]]" => resp
case _ =>
c.abort(c.enclosingPosition, s"Method ${m.name} in type ${m.owner} does not have required result type Future[Either[String, ?]]")
}
???
}
}
During the compilation it says Warning:scalac: scala.concurrent.Future[Either[String, Int]] which is right, however right after that it stops on the c.abort call which means the pattern doesn't match the type.
I even tried to debug it in REPL, but here is what I got:
val tq"scala.concurrent.Future[$a]" = typeOf[scala.concurrent.Future[Int]]
scala.MatchError: scala.concurrent.Future[Int] (of class
scala.reflect.internal.Types$ClassArgsTypeRef)
... 28 elided
I tried this many times already but always ended up with handling those types as Strings which is very unclear.
Thanks for reply!
I'd be grateful if someone showed an example of deconstructing Type using quasiquotes and pattern-matching. For now it seems to me that Type and quasiquotes are parts of different universes (not in Scala internals sense) and can't interact. The best way I know to do something like this is code like this:
val string = typeOf[String].dealias
val future = typeOf[scala.concurrent.Future[_]].typeConstructor
val either = typeOf[scala.util.Either[_, _]].typeConstructor
val respType = (for {
f <- Some(m.returnType.dealias) if f.typeConstructor == future // Future[_]
e <- f.typeArgs.headOption if e.typeConstructor == either // Future[Either[_,_]]
ea <- Some(e.typeArgs) if ea.head.dealias == string // Future[Either[String,_]]
} yield ea(1))
.getOrElse(c.abort(c.enclosingPosition, s"Method ${m.name} in type ${m.owner} does not have required result type Future[Either[String, ?]]"))
I use Some to wrap Type into Option and use for-comprehension syntax that IMHO makes it easier to understand what's going on, much easier than what you could get if you tried to use usual (non-quasiquotes-based) pattern matching on Type.
Update: Where tq"" works at all?`
From my experience the only context in which you can use tq"" to deconstruct type is in Macro annotations that can be used to annotate whole classes or method definitions. Consider following example:
import scala.concurrent.Future
import scala.util.Either
class Test {
#CheckReturnTypeMacroAnnotation
def foo1(): scala.concurrent.Future[scala.util.Either[String, Short]] = ???
#CheckReturnTypeMacroAnnotation
def foo2(): Future[Either[String, Int]] = ???
#CheckReturnTypeMacroAnnotation
def foo3(): scala.concurrent.Future[Either[String, Long]] = ???
#CheckReturnTypeMacroAnnotation
def foo4(): Future[scala.util.Either[String, Double]] = ???
#CheckReturnTypeMacroAnnotation
def fooBad() = scala.concurrent.Future.failed[scala.util.Either[String, Short]](new RuntimeException("Fake"))
}
We want CheckReturnTypeMacroAnnotation to ensure that the return type is of form scala.concurrent.Future[scala.util.Either[String, ?]]. We may implement CheckReturnTypeMacroAnnotation as
import scala.language.experimental.macros
import scala.annotation.{StaticAnnotation, compileTimeOnly}
#compileTimeOnly("enable macro to expand macro annotations")
class CheckReturnTypeMacroAnnotation extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro CheckReturnTypeMacro.process
}
object CheckReturnTypeMacro {
import scala.reflect.macros._
import scala.reflect.macros.whitebox.Context
def process(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val methodDef = annottees.map(_.tree).toList match {
case x :: Nil => x
case _ => c.abort(c.enclosingPosition, "Method definition is expected")
}
//c.warning(c.enclosingPosition, s"methodDef ${methodDef.getClass} => $methodDef")
val returnType = methodDef match {
case q"$mods def $name[..$tparams](...$paramss): $tpt = $body" => tpt
case _ => c.abort(c.enclosingPosition, "Method definition is expected")
}
//c.warning(NoPosition, s"returnType ${returnType.getClass} => $returnType")
val respType = returnType match {
case tq"scala.concurrent.Future[scala.util.Either[String, ${resp}]]" =>
c.warning(c.enclosingPosition, s"1 resp ${resp.getClass} => $resp")
resp
case tq"Future[Either[String, ${resp}]]" =>
c.warning(c.enclosingPosition, s"2 resp ${resp.getClass} => $resp")
resp
case tq"scala.concurrent.Future[Either[String, ${resp}]]" =>
c.warning(c.enclosingPosition, s"3 resp ${resp.getClass} => $resp")
resp
case tq"Future[scala.util.Either[String, ${resp}]]" =>
c.warning(c.enclosingPosition, s"4 resp ${resp.getClass} => $resp")
resp
case _ =>
c.abort(c.enclosingPosition, s"Method does not have required result type Future[Either[String, ?]]")
}
c.Expr[Any](methodDef) //this is in fact a no-op macro. it only does verification of return type
}
}
Note however how you have to handle various cases with different but similar tq"" patterns and that fooBad that does not explicitly specify return type will fail anyway. The output of an attempt to compile Test with this macro will generate an output like this:
Warning:(18, 8) 1 resp class scala.reflect.internal.Trees$Ident => Short
#CheckReturnTypeMacroAnnotation
Warning:(21, 8) 2 resp class scala.reflect.internal.Trees$Ident => Int
#CheckReturnTypeMacroAnnotation
Warning:(24, 8) 3 resp class scala.reflect.internal.Trees$Ident => Long
#CheckReturnTypeMacroAnnotation
Warning:(27, 8) 4 resp class scala.reflect.internal.Trees$Ident => Double
#CheckReturnTypeMacroAnnotation
Error:(31, 8) Method does not have required result type Future[Either[String, ?]]
#CheckReturnTypeMacroAnnotation
Note how all 4 cases actually present in the output and that fooBad has failed. The issue seems to come from the fact that macro is run before typechecker. Unfortunately I'm not aware of a way to make this pattern matching really work. I looked into reify and c.typecheck but had no luck.

Compiler crash in simple macro manipulating a match statement

def control(x: String): Option[String] = macro controlImpl
def controlImpl(c: Context)(x: c.Expr[String]): c.Expr[Option[String]] = {
import c.universe._
val result = x.tree match {
case Match(expr, cases) =>
val matchz = Match(q"""List("hello")""", cases)
q"Some(List(5)).map{a => $matchz}"
case a => a
}
c.Expr[Option[String]](result)
}
This macro crashes during macro expansion with the following error:
java.lang.IllegalArgumentException: Could not find proxy for val o7: Some in List(value o7, method apply, <$anon: Function1>, value f, method apply, <$anon: Function1>, method apply, <$anon: Function0>, value <local ApplicativeTest>, object ApplicativeTest, package scalaz, package <root>) (currentOwner= value one )
This is the macro application point:
val f = IdiomBracket.control {
a.get match {
case List(one) => one
case _ => ""
}
}
What is odd is that if you substitute q"Some(List(5)).map{a => $matchz}" with q"Some($matchz)" then the compiler crash goes away.
"Simple macro" is an oxymoron.
The crash is in lambda lift, which indicates a bad symbol owner.
You can inspect the tree you produce with -Ybrowse:typer.
Consider what you'd like to produce:
class X {
//def g = List("hello") match { case List(x) => x case _ => "" }
def f = Some(List(5)).map{a => List("hello") match { case List(x) => x case _ => "" } }
}
The var in the case is owned by the anonfun you want to create:
Symbol: [has] value x
Symbol owner: value $anonfun
Your actual result:
Symbol: [has] value x
Symbol owner: value <local Controlled>
where Controlled is my sample enclosing object for your code.
You might have to rebuild the cases, as opposed to just cases map (_.untypecheck).
https://github.com/scala/scala/blob/v2.11.5/src/reflect/scala/reflect/api/Trees.scala#L1100

Type bounds on functions

I am having trouble getting my code with parameterized types to pass the scala compiler. My goal is to be able to express (Predicate, Action) pairs as shown in the MyProg object.
trait ProgBase {
type Predicate[T] = T => Boolean
type Action[T] = T => Unit
private var prog = List[(Predicate[Any], Action[Any])]()
final def on[T <: Any](pred: Predicate[T])(action: Action[T]) = {
prog = (pred, action) :: prog // gives type mismatch
}
// remainder of trait elided
}
object MyProg extends ProgBase {
on[String](s => !s.isEmpty) { s =>
println(s + " is not empty")
}
on[Int](i => i.isValidByte) { i =>
println(i + " can fit in a byte")
}
}
By specifying that T has an upper bound of Any, I hoped this would appease the compiler, but clearly I am missing something:
[error] ......ProgBase.scala:8 type mismatch;
[error] found : (T => Boolean, T => Unit)
[error] required: (Any => Boolean, Any => Unit)
[error] prog = (pred, action) :: prog
[error] ^
First of all, answer to your question, if you write:
private var prog = List[(Predicate[_ <: Any], Action[_ <: Any])]()
It all compiles OK. We should use wildcards, 'cause the type of elements are unknown.
Second, maybe you mistyped, you can't use your on function as you used it, use it something like:
on[String](s => !s.isEmpty)(s => !s.isEmpty)
It caused by type mismatch: type Action[T] = T => Unit but println has type Unit,
so as a variant u can simply write: type Action = Unit. Obviously, u can avoid using this type alias at all.
Third, maybe you already know, and I shoudn't tell you, that in fact, you lose all information about predicate types - let's check it using Scala reflection:
import scala.reflect.runtime.{universe => ru}
def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
val s: String = "123"
val i: Int = 123
on[String](s => !s.isEmpty)(s => !s.isEmpty)
on[Int](i => i.isValidByte)(i => i.isValidByte)
getTypeTag((MyProg.prog.head._1)).tpe =:= ru.typeOf[(String) => Boolean] //>false!
So you see the problem.
To deal with it you can use heterogeneous lists. Lists and other various powerful structures you can find in shapeless: https://github.com/milessabin/shapeless

Hidden features of Scala

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What are the hidden features of Scala that every Scala developer should be aware of?
One hidden feature per answer, please.
Okay, I had to add one more. Every Regex object in Scala has an extractor (see answer from oxbox_lakes above) that gives you access to the match groups. So you can do something like:
// Regex to split a date in the format Y/M/D.
val regex = "(\\d+)/(\\d+)/(\\d+)".r
val regex(year, month, day) = "2010/1/13"
The second line looks confusing if you're not used to using pattern matching and extractors. Whenever you define a val or var, what comes after the keyword is not simply an identifier but rather a pattern. That's why this works:
val (a, b, c) = (1, 3.14159, "Hello, world")
The right hand expression creates a Tuple3[Int, Double, String] which can match the pattern (a, b, c).
Most of the time your patterns use extractors that are members of singleton objects. For example, if you write a pattern like
Some(value)
then you're implicitly calling the extractor Some.unapply.
But you can also use class instances in patterns, and that is what's happening here. The val regex is an instance of Regex, and when you use it in a pattern, you're implicitly calling regex.unapplySeq (unapply versus unapplySeq is beyond the scope of this answer), which extracts the match groups into a Seq[String], the elements of which are assigned in order to the variables year, month, and day.
Structural type definitions - i.e. a type described by what methods it supports. For example:
object Closer {
def using(closeable: { def close(): Unit }, f: => Unit) {
try {
f
} finally { closeable.close }
}
}
Notice that the type of the parameter closeable is not defined other than it has a close method
Type-Constructor Polymorphism (a.k.a. higher-kinded types)
Without this feature you can, for example, express the idea of mapping a function over a list to return another list, or mapping a function over a tree to return another tree. But you can't express this idea generally without higher kinds.
With higher kinds, you can capture the idea of any type that's parameterised with another type. A type constructor that takes one parameter is said to be of kind (*->*). For example, List. A type constructor that returns another type constructor is said to be of kind (*->*->*). For example, Function1. But in Scala, we have higher kinds, so we can have type constructors that are parameterised with other type constructors. So they're of kinds like ((*->*)->*).
For example:
trait Functor[F[_]] {
def fmap[A, B](f: A => B, fa: F[A]): F[B]
}
Now, if you have a Functor[List], you can map over lists. If you have a Functor[Tree], you can map over trees. But more importantly, if you have Functor[A] for any A of kind (*->*), you can map a function over A.
Extractors which allow you to replace messy if-elseif-else style code with patterns. I know that these are not exactly hidden but I've been using Scala for a few months without really understanding the power of them. For (a long) example I can replace:
val code: String = ...
val ps: ProductService = ...
var p: Product = null
if (code.endsWith("=")) {
p = ps.findCash(code.substring(0, 3)) //e.g. USD=, GBP= etc
}
else if (code.endsWith(".FWD")) {
//e.g. GBP20090625.FWD
p = ps.findForward(code.substring(0,3), code.substring(3, 9))
}
else {
p = ps.lookupProductByRic(code)
}
With this, which is much clearer in my opinion
implicit val ps: ProductService = ...
val p = code match {
case SyntheticCodes.Cash(c) => c
case SyntheticCodes.Forward(f) => f
case _ => ps.lookupProductByRic(code)
}
I have to do a bit of legwork in the background...
object SyntheticCodes {
// Synthetic Code for a CashProduct
object Cash extends (CashProduct => String) {
def apply(p: CashProduct) = p.currency.name + "="
//EXTRACTOR
def unapply(s: String)(implicit ps: ProductService): Option[CashProduct] = {
if (s.endsWith("=")
Some(ps.findCash(s.substring(0,3)))
else None
}
}
//Synthetic Code for a ForwardProduct
object Forward extends (ForwardProduct => String) {
def apply(p: ForwardProduct) = p.currency.name + p.date.toString + ".FWD"
//EXTRACTOR
def unapply(s: String)(implicit ps: ProductService): Option[ForwardProduct] = {
if (s.endsWith(".FWD")
Some(ps.findForward(s.substring(0,3), s.substring(3, 9))
else None
}
}
But the legwork is worth it for the fact that it separates a piece of business logic into a sensible place. I can implement my Product.getCode methods as follows..
class CashProduct {
def getCode = SyntheticCodes.Cash(this)
}
class ForwardProduct {
def getCode = SyntheticCodes.Forward(this)
}
Manifests which are a sort of way at getting the type information at runtime, as if Scala had reified types.
In scala 2.8 you can have tail-recursive methods by using the package scala.util.control.TailCalls (in fact it's trampolining).
An example:
def u(n:Int):TailRec[Int] = {
if (n==0) done(1)
else tailcall(v(n/2))
}
def v(n:Int):TailRec[Int] = {
if (n==0) done(5)
else tailcall(u(n-1))
}
val l=for(n<-0 to 5) yield (n,u(n).result,v(n).result)
println(l)
Case classes automatically mixin the Product trait, providing untyped, indexed access to the fields without any reflection:
case class Person(name: String, age: Int)
val p = Person("Aaron", 28)
val name = p.productElement(0) // name = "Aaron": Any
val age = p.productElement(1) // age = 28: Any
val fields = p.productIterator.toList // fields = List[Any]("Aaron", 28)
This feature also provides a simplified way to alter the output of the toString method:
case class Person(name: String, age: Int) {
override def productPrefix = "person: "
}
// prints "person: (Aaron,28)" instead of "Person(Aaron, 28)"
println(Person("Aaron", 28))
It's not exactly hidden, but certainly a under advertised feature: scalac -Xprint.
As a illustration of the use consider the following source:
class A { "xx".r }
Compiling this with scalac -Xprint:typer outputs:
package <empty> {
class A extends java.lang.Object with ScalaObject {
def this(): A = {
A.super.this();
()
};
scala.this.Predef.augmentString("xx").r
}
}
Notice scala.this.Predef.augmentString("xx").r, which is a the application of the implicit def augmentString present in Predef.scala.
scalac -Xprint:<phase> will print the syntax tree after some compiler phase. To see the available phases use scalac -Xshow-phases.
This is a great way to learn what is going on behind the scenes.
Try with
case class X(a:Int,b:String)
using the typer phase to really feel how useful it is.
You can define your own control structures. It's really just functions and objects and some syntactic sugar, but they look and behave like the real thing.
For example, the following code defines dont {...} unless (cond) and dont {...} until (cond):
def dont(code: => Unit) = new DontCommand(code)
class DontCommand(code: => Unit) {
def unless(condition: => Boolean) =
if (condition) code
def until(condition: => Boolean) = {
while (!condition) {}
code
}
}
Now you can do the following:
/* This will only get executed if the condition is true */
dont {
println("Yep, 2 really is greater than 1.")
} unless (2 > 1)
/* Just a helper function */
var number = 0;
def nextNumber() = {
number += 1
println(number)
number
}
/* This will not be printed until the condition is met. */
dont {
println("Done counting to 5!")
} until (nextNumber() == 5)
#switch annotation in Scala 2.8:
An annotation to be applied to a match
expression. If present, the compiler
will verify that the match has been
compiled to a tableswitch or
lookupswitch, and issue an error if it
instead compiles into a series of
conditional expressions.
Example:
scala> val n = 3
n: Int = 3
scala> import annotation.switch
import annotation.switch
scala> val s = (n: #switch) match {
| case 3 => "Three"
| case _ => "NoThree"
| }
<console>:6: error: could not emit switch for #switch annotated match
val s = (n: #switch) match {
Dunno if this is really hidden, but I find it quite nice.
Typeconstructors that take 2 type parameters can be written in infix notation
object Main {
class FooBar[A, B]
def main(args: Array[String]): Unit = {
var x: FooBar[Int, BigInt] = null
var y: Int FooBar BigInt = null
}
}
Scala 2.8 introduced default and named arguments, which made possible the addition of a new "copy" method that Scala adds to case classes. If you define this:
case class Foo(a: Int, b: Int, c: Int, ... z:Int)
and you want to create a new Foo that's like an existing Foo, only with a different "n" value, then you can just say:
foo.copy(n = 3)
in scala 2.8 you can add #specialized to your generic classes/methods. This will create special versions of the class for primitive types (extending AnyVal) and save the cost of un-necessary boxing/unboxing :
class Foo[#specialized T]...
You can select a subset of AnyVals :
class Foo[#specialized(Int,Boolean) T]...
Extending the language. I always wanted to do something like this in Java (couldn't). But in Scala I can have:
def timed[T](thunk: => T) = {
val t1 = System.nanoTime
val ret = thunk
val time = System.nanoTime - t1
println("Executed in: " + time/1000000.0 + " millisec")
ret
}
and then write:
val numbers = List(12, 42, 3, 11, 6, 3, 77, 44)
val sorted = timed { // "timed" is a new "keyword"!
numbers.sortWith(_<_)
}
println(sorted)
and get
Executed in: 6.410311 millisec
List(3, 3, 6, 11, 12, 42, 44, 77)
You can designate a call-by-name parameter (EDITED: this is different then a lazy parameter!) to a function and it will not be evaluated until used by the function (EDIT: in fact, it will be reevaluated every time it is used). See this faq for details
class Bar(i:Int) {
println("constructing bar " + i)
override def toString():String = {
"bar with value: " + i
}
}
// NOTE the => in the method declaration. It indicates a lazy paramter
def foo(x: => Bar) = {
println("foo called")
println("bar: " + x)
}
foo(new Bar(22))
/*
prints the following:
foo called
constructing bar 22
bar with value: 22
*/
You can use locally to introduce a local block without causing semicolon inference issues.
Usage:
scala> case class Dog(name: String) {
| def bark() {
| println("Bow Vow")
| }
| }
defined class Dog
scala> val d = Dog("Barnie")
d: Dog = Dog(Barnie)
scala> locally {
| import d._
| bark()
| bark()
| }
Bow Vow
Bow Vow
locally is defined in "Predef.scala" as:
#inline def locally[T](x: T): T = x
Being inline, it does not impose any additional overhead.
Early Initialization:
trait AbstractT2 {
println("In AbstractT2:")
val value: Int
val inverse = 1.0/value
println("AbstractT2: value = "+value+", inverse = "+inverse)
}
val c2c = new {
// Only initializations are allowed in pre-init. blocks.
// println("In c2c:")
val value = 10
} with AbstractT2
println("c2c.value = "+c2c.value+", inverse = "+c2c.inverse)
Output:
In AbstractT2:
AbstractT2: value = 10, inverse = 0.1
c2c.value = 10, inverse = 0.1
We instantiate an anonymous inner
class, initializing the value field
in the block, before the with
AbstractT2 clause. This guarantees
that value is initialized before the
body of AbstractT2 is executed, as
shown when you run the script.
You can compose structural types with the 'with' keyword
object Main {
type A = {def foo: Unit}
type B = {def bar: Unit}
type C = A with B
class myA {
def foo: Unit = println("myA.foo")
}
class myB {
def bar: Unit = println("myB.bar")
}
class myC extends myB {
def foo: Unit = println("myC.foo")
}
def main(args: Array[String]): Unit = {
val a: A = new myA
a.foo
val b: C = new myC
b.bar
b.foo
}
}
placeholder syntax for anonymous functions
From The Scala Language Specification:
SimpleExpr1 ::= '_'
An expression (of syntactic category Expr) may contain embedded underscore symbols _ at places where identifiers are legal. Such an expression represents an anonymous function where subsequent occurrences of underscores denote successive parameters.
From Scala Language Changes:
_ + 1 x => x + 1
_ * _ (x1, x2) => x1 * x2
(_: Int) * 2 (x: Int) => x * 2
if (_) x else y z => if (z) x else y
_.map(f) x => x.map(f)
_.map(_ + 1) x => x.map(y => y + 1)
Using this you could do something like:
def filesEnding(query: String) =
filesMatching(_.endsWith(query))
Implicit definitions, particularly conversions.
For example, assume a function which will format an input string to fit to a size, by replacing the middle of it with "...":
def sizeBoundedString(s: String, n: Int): String = {
if (n < 5 && n < s.length) throw new IllegalArgumentException
if (s.length > n) {
val trailLength = ((n - 3) / 2) min 3
val headLength = n - 3 - trailLength
s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length)
} else s
}
You can use that with any String, and, of course, use the toString method to convert anything. But you could also write it like this:
def sizeBoundedString[T](s: T, n: Int)(implicit toStr: T => String): String = {
if (n < 5 && n < s.length) throw new IllegalArgumentException
if (s.length > n) {
val trailLength = ((n - 3) / 2) min 3
val headLength = n - 3 - trailLength
s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length)
} else s
}
And then, you could pass classes of other types by doing this:
implicit def double2String(d: Double) = d.toString
Now you can call that function passing a double:
sizeBoundedString(12345.12345D, 8)
The last argument is implicit, and is being passed automatically because of the implicit de declaration. Furthermore, "s" is being treated like a String inside sizeBoundedString because there is an implicit conversion from it to String.
Implicits of this type are better defined for uncommon types to avoid unexpected conversions. You can also explictly pass a conversion, and it will still be implicitly used inside sizeBoundedString:
sizeBoundedString(1234567890L, 8)((l : Long) => l.toString)
You can also have multiple implicit arguments, but then you must either pass all of them, or not pass any of them. There is also a shortcut syntax for implicit conversions:
def sizeBoundedString[T <% String](s: T, n: Int): String = {
if (n < 5 && n < s.length) throw new IllegalArgumentException
if (s.length > n) {
val trailLength = ((n - 3) / 2) min 3
val headLength = n - 3 - trailLength
s.substring(0, headLength)+"..."+s.substring(s.length - trailLength, s.length)
} else s
}
This is used exactly the same way.
Implicits can have any value. They can be used, for instance, to hide library information. Take the following example, for instance:
case class Daemon(name: String) {
def log(msg: String) = println(name+": "+msg)
}
object DefaultDaemon extends Daemon("Default")
trait Logger {
private var logd: Option[Daemon] = None
implicit def daemon: Daemon = logd getOrElse DefaultDaemon
def logTo(daemon: Daemon) =
if (logd == None) logd = Some(daemon)
else throw new IllegalArgumentException
def log(msg: String)(implicit daemon: Daemon) = daemon.log(msg)
}
class X extends Logger {
logTo(Daemon("X Daemon"))
def f = {
log("f called")
println("Stuff")
}
def g = {
log("g called")(DefaultDaemon)
}
}
class Y extends Logger {
def f = {
log("f called")
println("Stuff")
}
}
In this example, calling "f" in an Y object will send the log to the default daemon, and on an instance of X to the Daemon X daemon. But calling g on an instance of X will send the log to the explicitly given DefaultDaemon.
While this simple example can be re-written with overload and private state, implicits do not require private state, and can be brought into context with imports.
Maybe not too hidden, but I think this is useful:
#scala.reflect.BeanProperty
var firstName:String = _
This will automatically generate a getter and setter for the field that matches bean convention.
Further description at developerworks
Implicit arguments in closures.
A function argument can be marked as implicit just as with methods. Within the scope of the body of the function the implicit parameter is visible and eligible for implicit resolution:
trait Foo { def bar }
trait Base {
def callBar(implicit foo: Foo) = foo.bar
}
object Test extends Base {
val f: Foo => Unit = { implicit foo =>
callBar
}
def test = f(new Foo {
def bar = println("Hello")
})
}
Build infinite data structures with Scala's Streams :
http://www.codecommit.com/blog/scala/infinite-lists-for-the-finitely-patient
Result types are dependent on implicit resolution. This can give you a form of multiple dispatch:
scala> trait PerformFunc[A,B] { def perform(a : A) : B }
defined trait PerformFunc
scala> implicit val stringToInt = new PerformFunc[String,Int] {
def perform(a : String) = 5
}
stringToInt: java.lang.Object with PerformFunc[String,Int] = $anon$1#13ccf137
scala> implicit val intToDouble = new PerformFunc[Int,Double] {
def perform(a : Int) = 1.0
}
intToDouble: java.lang.Object with PerformFunc[Int,Double] = $anon$1#74e551a4
scala> def foo[A, B](x : A)(implicit z : PerformFunc[A,B]) : B = z.perform(x)
foo: [A,B](x: A)(implicit z: PerformFunc[A,B])B
scala> foo("HAI")
res16: Int = 5
scala> foo(1)
res17: Double = 1.0
Scala's equivalent of Java double brace initializer.
Scala allows you to create an anonymous subclass with the body of the class (the constructor) containing statements to initialize the instance of that class.
This pattern is very useful when building component-based user interfaces (for example Swing , Vaadin) as it allows to create UI components and declare their properties more concisely.
See http://spot.colorado.edu/~reids/papers/how-scala-experience-improved-our-java-development-reid-2011.pdf for more information.
Here is an example of creating a Vaadin button:
val button = new Button("Click me"){
setWidth("20px")
setDescription("Click on this")
setIcon(new ThemeResource("icons/ok.png"))
}
Excluding members from import statements
Suppose you want to use a Logger that contains a println and a printerr method, but you only want to use the one for error messages, and keep the good old Predef.println for standard output. You could do this:
val logger = new Logger(...)
import logger.printerr
but if logger also contains another twelve methods that you would like to import and use, it becomes inconvenient to list them. You could instead try:
import logger.{println => donotuseprintlnt, _}
but this still "pollutes" the list of imported members. Enter the über-powerful wildcard:
import logger.{println => _, _}
and that will do just the right thing™.
require method (defined in Predef) that allow you to define additional function constraints that would be checked during run-time. Imagine that you developing yet another twitter client and you need to limit tweet length up to 140 symbols. Moreover you can't post empty tweet.
def post(tweet: String) = {
require(tweet.length < 140 && tweet.length > 0)
println(tweet)
}
Now calling post with inappropriate length argument will cause an exception:
scala> post("that's ok")
that's ok
scala> post("")
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:145)
at .post(<console>:8)
scala> post("way to looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong tweet")
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:145)
at .post(<console>:8)
You can write multiple requirements or even add description to each:
def post(tweet: String) = {
require(tweet.length > 0, "too short message")
require(tweet.length < 140, "too long message")
println(tweet)
}
Now exceptions are verbose:
scala> post("")
java.lang.IllegalArgumentException: requirement failed: too short message
at scala.Predef$.require(Predef.scala:157)
at .post(<console>:8)
One more example is here.
Bonus
You can perform an action every time requirement fails:
scala> var errorcount = 0
errorcount: Int = 0
def post(tweet: String) = {
require(tweet.length > 0, {errorcount+=1})
println(tweet)
}
scala> errorcount
res14: Int = 0
scala> post("")
java.lang.IllegalArgumentException: requirement failed: ()
at scala.Predef$.require(Predef.scala:157)
at .post(<console>:9)
...
scala> errorcount
res16: Int = 1
Traits with abstract override methods are a feature in Scala that is as not widely advertised as many others. The intend of methods with the abstract override modifier is to do some operations and delegating the call to super. Then these traits have to be mixed-in with concrete implementations of their abstract override methods.
trait A {
def a(s : String) : String
}
trait TimingA extends A {
abstract override def a(s : String) = {
val start = System.currentTimeMillis
val result = super.a(s)
val dur = System.currentTimeMillis-start
println("Executed a in %s ms".format(dur))
result
}
}
trait ParameterPrintingA extends A {
abstract override def a(s : String) = {
println("Called a with s=%s".format(s))
super.a(s)
}
}
trait ImplementingA extends A {
def a(s: String) = s.reverse
}
scala> val a = new ImplementingA with TimingA with ParameterPrintingA
scala> a.a("a lotta as")
Called a with s=a lotta as
Executed a in 0 ms
res4: String = sa attol a
While my example is really not much more than a poor mans AOP, I used these Stackable Traits much to my liking to build Scala interpreter instances with predefined imports, custom bindings and classpathes. The Stackable Traits made it possible to create my factory along the lines of new InterpreterFactory with JsonLibs with LuceneLibs and then have useful imports and scope varibles for the users scripts.