views:

3383

answers:

21

What are the hidden features of Scala that every Scala developer should be aware of?

One hidden feature per answer, please.

+17  A: 

Manifests which are a sort of way at getting the type information at runtime, as if Scala had reified types.

oxbow_lakes
I think it's preferable to explain the answer _in_ the answer rather than referring to a link. By the way, hi agai oxbow! :-)
Daniel
This is a truly hidden feature... not even in the API docs. Very useful though.
André Laszlo
+21  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)     
}
oxbow_lakes
isn't this like a switch? maybe this could be refactored more.
Geo
Patterns are like turbo-charged switches: much more powerful and clear
oxbow_lakes
How is extractors a hidden feature? o_O
missingfaktor
@Rahul - you at least read up to my 2nd sentence, right?
oxbow_lakes
@oxbow_lakes: Oops. I actually didn't. I just glanced over the answer and posted the comment. Sorry.
missingfaktor
+6  A: 

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

agilefall
And you can make shortcut for it if you use it a lot, e.g.: import scala.reflect.{BeanProperty => BP}
Alexey
+13  A: 

You can designate a lazy parameter to a function and it will not be evaluated until used by the function. 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
*/
agilefall
I thought "x: => Bar" meant that x was a function that took no parameters and returned a Bar. So, "new bar(22)" is just an anonymous function, and is evaluated as a function like any other function.
Alex Black
"x: ()=>Bar" defines x a function that takes no parameters and returns a Bar. x: => Bar defines x as call by name. Take a look at http://scala.sygneca.com/faqs/language#what-s-the-difference-between-a-lazy-argument-a-no-arg-function-argument-and-a-lazy-value for more details
agilefall
What you show is call-by-name parameters. Lazy parameters aren't implemented yet: https://lampsvn.epfl.ch/trac/scala/ticket/240
ArtemGr
+6  A: 

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: int) * 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))
eed3si9n
This should be referred to as 'placeholder syntax for anonymous functions'. Implicit has a distinct meaning in Scala, and it isn't related to this.
retronym
The link has a non-obvious relationship to the answer. "implicit" is not the correct term for this. As above it should be "placeholder."
Alain O'Dea
+19  A: 

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

oxbow_lakes
This is cald structural types. Please correct the answer.
Daniel
That should have been "called". My browser is eating keytouches. Unfortunately, for real. :-(
Daniel
Thanks Daniel - corrected
oxbow_lakes
Structural types aren't even mentioned in "Programming in Scala". They're a bit slower than other techniques for passing types though since they use reflection to call the right methods. (Hopefully they'll come up with a way to speed that up.)
Ken Bloom
And there is also possible to make alias for them, what works like externally assigned interface (very slow one):type Closeable = { def close(): Unit }
Alexey
+8  A: 

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.

Daniel
+18  A: 

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.

Apocalisp
+13  A: 

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) 
Aleksander Kmetec
Some more examples here: http://programmers.stackexchange.com/questions/13072/alternatives-to-if-else-statement/13086#13086
missingfaktor
+12  A: 

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)
Willis Blackburn
WARNING: copy method will not be overriden if you inherit one case class from another. So you have to override it manually
Alexey
Related: Cleaner way to update nested structures http://stackoverflow.com/q/3900307/203968
oluies
case class is no longer (Scala 2.8) allowed to inherit from a case class. Thank you lord of Scala for deprecating this unholy inheritance.
olle kullberg
+19  A: 

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.

Willis Blackburn
This one is really hidden and both useful, would worth to be upvoted more times.
thSoft
+10  A: 

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)
Aymen
What is trampolining?
missingfaktor
+9  A: 

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

Aymen
+5  A: 

Build infinite data structures with Scala's Streams : http://www.codecommit.com/blog/scala/infinite-lists-for-the-finitely-patient

Aymen
+7  A: 

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.

missingfaktor
The construct is called "early initialization."
Randall Schulz
+8  A: 

@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 {
missingfaktor
+6  A: 

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
jsuereth
That might be the case, but the session above is misleading. The definition of `foo` uses an `a` which must have been present in the environment prior to the execution of these commands. I assume you meant `z.perform(x)`.
Daniel
+9  A: 

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.

missingfaktor
+7  A: 

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.

pedrofurla
+1  A: 

How you can easily "extend" the language. I always wanted to do something like this in Java (but 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)
Adrian
+4  A: 

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)) 
Aaron Novstrup