Scala 2.10
Czech Scala Enthusiasts May 28th 2013
Jakub Janeček
What does it bring?
Language Modularization
Language Modularization
• some features are confusing, “dangerous” or still experimental
Language Modularization
• some features are confusing, “dangerous” or still experimental
• since 2.10 they have to be explicitly enabled (otherwise warning or error is emitted)
Language Modularization
• some features are confusing, “dangerous” or still experimental
• since 2.10 they have to be explicitly enabled (otherwise warning or error is emitted)
• for example: – implicit conversions
Language Modularization
• some features are confusing, “dangerous” or still experimental
• since 2.10 they have to be explicitly enabled (otherwise warning or error is emitted)
• for example: – implicit conversions – macros
Example: Postfix Operators
List(1, 2, 3) reverse
Example: Postfix Operators
List(1, 2, 3) reverse
import language.postfixOps
Example: Postfix Operators
List(1, 2, 3) reverse
> scalac –language:postfixOps
What does it bring?
String Interpolation
String Interpolation
• Remember?
"1 + 1 = " + (1 + 1)
String Interpolation
• Remember?
"1 + 1 = " + (1 + 1)
• No more!
s"1 + 1 = ${1 + 1}"
String Interpolation
"1 + 1 = " + (1 + 1)
• No more!
s"1 + 1 = ${1 + 1}"
Standard interpolator We also have f and raw
Escape character
• Remember?
Example: Interpolator rev
def rev(args: Any*): String = … • Extension method of StringContext:
Example: Interpolator rev
def rev(args: Any*): String = …
rev”this will be reversed"
• Extension method of StringContext:
What does it bring?
“value”
Value Classes
Value Classes
• allow extends AnyVal
Value Classes
• allow extends AnyVal • compiler can usually avoid allocating runtime
objects à performance with type safety
Value Classes
• allow extends AnyVal • compiler can usually avoid allocating runtime
objects à performance with type safety • they have limitations
Example: MyInt
case class MyInt(val underlying: Int) extends AnyVal { def plusOne = MyInt(underlying + 1) } MyInt(5).plusOne
Example: MyInt
case class MyInt(val underlying: Int) extends AnyVal { def plusOne = MyInt(underlying + 1) } MyInt(5).plusOne
Example: MyInt
case class MyInt(val underlying: Int) extends AnyVal { def plusOne = MyInt(underlying + 1) } MyInt(5).plusOne
MyInt$.MODULE$.plusOne$extension(5)
What does it bring?
Cute Puppy
Cute Puppy Implicit Classes
Implicit Classes
• remove a lot of boilerplate code
Implicit Classes
• remove a lot of boilerplate code • class must have only one parameter in its
constructor's first parameter list
Implicit Classes
• remove a lot of boilerplate code • class must have only one parameter in its
constructor's first parameter list • implicit conversion is generated
Implicit Classes
• remove a lot of boilerplate code • class must have only one parameter in its
constructor's first parameter list • implicit conversion is generated • often used with Value Classes
Implicit Classes
• remove a lot of boilerplate code • class must have only one parameter in its
constructor's first parameter list • implicit conversion is generated • often used with Value Classes • must be defined inside other class/trait/object
Example: MyInt
implicit class MyInt(val i: Int) extends AnyVal { def plusOne = i + 1 } 2.plusOne
Example: MyInt
implicit class MyInt(val i: Int) extends AnyVal { def plusOne = i + 1 } 2.plusOne
What does it bring?
Trait Dynamic
Trait Dynamic
• allows calling methods not existing in the static type
Trait Dynamic
• allows calling methods not existing in the static type
• useful for DSLs and integration with dynamic languages
Trait Dynamic
• allows calling methods not existing in the static type
• useful for DSLs and integration with dynamic languages
• empty marker trait Dynamic
Trait Dynamic
• allows calling methods not existing in the static type
• useful for DSLs and integration with dynamic languages
• empty marker trait Dynamic • if type check fails it is rewritten to one of
– applyDynamic – applyDynamicNamed – selectDynamic – updateDynamic
Example: Dynamic DB
case class Record(id: Long, name: String)
Example: Dynamic DB
case class Record(id: Long, name: String) object Record extends Dynamic { def applyDynamic(sel: String) (arg: Any): Record = … }
Example: Dynamic DB
case class Record(id: Long, name: String) object Record extends Dynamic { def applyDynamic(sel: String) (arg: Any): Record = … }
Record.findById(1)
Example: Dynamic DB
case class Record(id: Long, name: String) object Record extends Dynamic { def applyDynamic(sel: String) (arg: Any): Record = … }
Record.findById(1) Record.applyDynamic("findById")(1)
What does it bring?
Macros
Macros
• compile-time metaprogramming
Macros
• compile-time metaprogramming • basically functions that are loaded and
executed by the compiler
Macros
• compile-time metaprogramming • basically functions that are loaded and
executed by the compiler – given context and AST of arguments
Macros
• compile-time metaprogramming • basically functions that are loaded and
executed by the compiler – given context and AST of arguments – returned AST inlined and type-checked at the
call site
Example: logging
logger.debug(s"${expensive} message!")
Example: logging
if (logger.isDebugEnabled) { logger.debug(s"${expensive} message!") }
Example: logging
if (logger.isDebugEnabled) { logger.debug(s"${expensive} message!") }
macro
Example: logging
if (logger.isDebugEnabled) { logger.debug(s"${expensive} message!") }
macro expanded at compile-time
And last…
Triple Question Mark
def complexMethod() = ??? • Defined in class Predef def ??? : Nothing = throw new NotImplementedError