Some Scala code examples which are by no means exhaustive but just some things I wanted to write down.
Options
val foo = Option ( 1 ) // or None
def bar ( a : Int ) = a + 1
// The match:
foo match {
case Some ( f ) => bar ( f )
case None => - 1
}
// ...is equivalent to:
foo map bar getOrElse - 1
// ...or since Scala 2.10:
foo . fold (- 1 )( bar )
foo . isEmpty
// is equivalent to:
foo . fold ( true )( _ => false )
Compiling a match expression to a tableswitch or lookupswitch is much more performant because it results in a branch table rather than a decision tree. Such as in the code:
val i = 1
val x = i match {
case 1 => "Foo"
case 2 => "Bar"
case _ => "Baz"
}
The code with a value rather than an integer literal:
val i = 1
val Two = 2
val x = i match {
case 1 => "Foo"
case Two => "Bar"
case _ => "Baz"
}
…could not be compiled to a tableswitch. However the code:
import scala.annotation.switch
val i = 1
val Two = 2
val x = ( i : @switch ) match {
case 1 => "Foo"
case Two => "Bar"
case _ => "Baz"
}
…yields a warning that a tableswitch is not being created.
Enriching
// add method using 'pimp (enrich) my library pattern':
class SpecialList ( list : List [ String ]) {
def special = list . filter ( _ . startsWith ( "foo" ))
}
implicit def listToSpecialList ( list : List [ String ]) = new SpecialList ( list )
val list = List ( "foobar" , "bazqux" )
list . special
// add method using implicit classes (Scala 2.10 onwards):
implicit class SpecialList ( list : List [ String ]) {
def special = list . filter ( _ . startsWith ( "foo" ))
}
val list = List ( "foobar" , "bazqux" )
list . special
// 'add' method using composition
case class SpecialList (
list : List [ String ]
) {
def special = list . filter ( _ . startsWith ( "foo" ))
}
val list = SpecialList ( List ( "foobar" , "bazqux" ))
list . special
Loops
val items = Array ( "Hello" , ", " , "World!" )
val moreitems = Array . apply ( "Hello" , ", " , "World!" )
items . foreach ( arg => println ( arg ))
items . foreach (( arg : String ) => println ( arg ))
val greetStrings = new Array [ String ]( 3 )
greetStrings . update ( 0 , "Hello" )
greetStrings . update ( 1 , ", " )
greetStrings . update ( 2 , "World!" )
// long-hand
for ( i <- 0. to ( 2 ))
print ( greetStrings . apply ( i ))
// but equivalent to
for ( i <- 0 to 2 )
print ( greetStrings ( i ))
Lists
val emptyList = List ()
val otherEmptyList = Nil
val items = List ( "foo" , "bar" , "baz" )
val consStyleItems = "foo" :: "bar" :: "baz" :: Nil // cons prepend to front of Nil list
val concatStyleItems = List ( "foo" , "bar" ) ::: List ( "baz" )
items ( 2 ) // returns 'baz'
items . count ( s => s . length == 3 ) // counts number of items with length of three chars
items . drop ( 2 ) // drops first two elements and returns rest of list
items . dropRight ( 2 ) // drops RIGHT MOST two elements and returns rest of list
items . exists ( s => s == "bar" ) // boolean: contains item?
items . forall ( s => s . startsWith ( "b" )) // Boolean: all items start with "b"
items . forall ( s => s . length == 3 ) // Boolean: all items three chars long
items . foreach ( print )
items . isEmpty // Boolean
items . head // first item
items . init // all but the last item
items . last // the last item
items . tail // list minus first element
items . length // Int
val extraItems = items ::: List ( "password" , "extra" )
extraItems . filter ( s => s . length == 3 ) // filters only strings with three chars
extraItems . foreach ( s => s . startsWith ( "b" ))
extraItems . map ( s => "x" + s + "x" )
extraItems . map ( s => if ( s == "password" ) { "[redacted]" } else { s })
extraItems . filterNot ( s => s . length > 3 ) // new list without the matching items
extraItems . mkString ( ", " ) // make a String out of the List
extraItems . reverse
extraItems . sortBy ( s => s )
def printItemsImperative ( items : Array [ String ]) : Unit = {
var i = 0
while ( i < items . length ) {
println ( items ( i ))
i += 1
}
}
def printItemsFunctional ( items : Array [ String ]) : Unit = {
for ( item <- items )
println ( item )
}
def printItemsFunctionalShort ( items : Array [ String ]) : Unit = {
items . foreach ( println )
}
def printItemsPureFunctional ( items : Array [ String ]) = {
items . mkString ( "\n" )
}
val items = Array ( "one" , "two" , "three" )
printItemsImperative ( items )
printItemsFunctional ( items )
printItemsFunctionalShort ( items )
println ( printItemsPureFunctional ( items ))
// makes the pure functional method easy to test:
assert ( printItemsPureFunctional ( items ) == "one\ntwo\nthree" )
val lines = Array ( "This is a line" , "and this is another line" , "so's this!" )
val longestLine = lines . reduceLeft (( a , b ) => if ( a . length > b . length ) a else b )
Placeholder Syntax
val l = List ( 1 , 3 , 4 , 6 , 1 , 3 , 4 , 9 , 4 , 6 , 2 )
l . filter (( x : Int ) => x > 4 )
l . filter (( x ) => x > 4 )
l . filter ( x => x > 4 )
l . filter ( _ > 4 )
Partially-applied functions
// the function
def sum ( a : Int , b : Int , c : Int ) = a + b + c
sum ( 1 , 2 , 3 )
// create function value object
val s = sum _
s ( 1 , 2 , 3 )
// is the short form of
s . apply ( 1 , 2 , 3 ) // which forwards params to sum then returns results
// apply to one of the params with two other new ones
val s2 = sum ( 1 , _: Int , 3 )
s2 ( 2 )
Parameters
// repeated parameters
def echo ( args : String* ) = for ( arg <- args ) println ( arg )
val args = Array ( "one" , "two" , "three" )
// pass each element of array to echo, rather than as an Array
echo ( args : _ * )
// named arguments
def speed ( distance : Float , time : Float ) : Float = distance / time
speed ( 100 , 10 )
speed ( time = 10 , distance = 100 )
// default parameters
def greet ( name : String = "World" ) = println ( s "Hello, $name!" )
greet ( "Beth" )
greet ()
Tail recursion vs imperative loop
def countFromRecursive ( x : Int ) : Int =
if ( x > 9 ) x
else countFromRecursive ( x + 1 )
def countFromLoop ( x : Int ) : Int = {
var current = x
while ( current < 10 )
current += 1
current
}
// new stack frame for each call
def notTailRecursive ( x : Int ) : Int =
if ( x == 0 ) throw new Exception ()
else notTailRecursive ( x - 1 ) + 1
// single stack frame
def tailRecursive ( x : Int ) : Int =
if ( x == 0 ) throw new Exception ()
else tailRecursive ( x - 1 )
// no tail-call optimisation
val funValueObject = nestedFunction _
def nestedFunction ( x : Int ) {
if ( x != 0 ) {
println ( x )
funValueObject ( x - 1 )
}
}
String interpolation
// s interpolator
val name = "World"
println ( s "Hello, $name!" )
// f interpolator, like printf
val population = 7.125d
println ( f "Hello all $population%2.2f billion people in the world!" )
// escaped string
s "x\ny"
// no formatting
raw "x\ny"
Tuples
// finite ordered list of heterogeneous immutable elements
val t = ( 4 , 3 , 2 , 1 )
val sum = t . _1 + t . _2 + t . _3 + t . _4
t . productIterator . foreach ( println )
val t = ( 1 , "hello" , Console )
// is equal to
val t = new Tuple3 ( 1 , "hello" , Console )
Case class with trait-implemented function
trait Greeter {
val name : String
def render : String = "Hello, " + name + "!"
}
object Hello {
case class greet ( name : String ) extends Greeter
}
Hello . greet ( "World" ). render
Futures
import scala.util._
import scala.concurrent._
import ExecutionContext.Implicits.global
val f : Future [ List [ String ]] = future {
Thread . sleep ( 200 ) // do something expensive
List ( "Hello, World!" , "Goodbye, World!" )
}
// then:
f onSuccess {
case messages => for ( message <- messages ) println ( message )
}
f onFailure {
case t => println ( "An error has occured: " + t . getMessage )
}
// or, concisely:
f onComplete {
case Success ( messages ) => for ( message <- messages ) println ( message )
case Failure ( t ) => println ( "An error has occured: " + t . getMessage )
}
Serialized Futures using flatMap
import scala.util._
import scala.concurrent._
import ExecutionContext.Implicits.global
val f1 : Future [ String ] = Future {
Thread . sleep ( 200 )
"done 1..."
}
val f2 : Future [ String ] = Future {
Thread . sleep ( 200 )
"done 2..."
}
val serializedFutures : Future [ String ] = f1 flatMap ( res1 => f2 )
f1 onComplete {
case Success ( result ) => println ( result )
case Failure ( t ) => println ( "An error has occured: " + t . getMessage )
}
f2 onComplete {
case Success ( result ) => println ( result )
case Failure ( t ) => println ( "An error has occured: " + t . getMessage )
}
serializedFutures onComplete {
case resTry => println ( "Both Done: Success=" + resTry . isSuccess )
}
Serialized Futures using for comprehension
import scala.util._
import scala.concurrent._
import ExecutionContext.Implicits.global
val f1 : Future [ String ] = Future {
Thread . sleep ( 200 )
"done 1..."
}
val f2 : Future [ String ] = Future {
Thread . sleep ( 200 )
"done 2..."
}
def combine ( s1 : String , s12 : String ) : String = "result"
val serializedFutures = for {
val1 <- f1
val2 <- f2
} yield combine ( val1 , val2 )
f1 onComplete {
case Success ( result ) => println ( result )
case Failure ( t ) => println ( "An error has occured: " + t . getMessage )
}
f2 onComplete {
case Success ( result ) => println ( result )
case Failure ( t ) => println ( "An error has occured: " + t . getMessage )
}
serializedFutures onComplete {
case resTry => println ( "Both Done: Success=" + resTry . isSuccess )
}
BLOCKING Futures using Awaits
import scala.concurrent. { Await , Future }
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util. { Success , Failure }
val f1 : Future [ String ] = Future {
Thread . sleep ( 200 )
"done 1..."
}
val f2 : Future [ String ] = Future {
Thread . sleep ( 200 )
"done 2..."
}
Await . result ( f1 , 10 seconds )
Await . result ( f2 , 10 seconds )
f1 onComplete {
case Success ( result ) => println ( result )
case Failure ( t ) => println ( "An error has occured: " + t . getMessage )
}
f2 onComplete {
case Success ( result ) => println ( result )
case Failure ( t ) => println ( "An error has occured: " + t . getMessage )
}
XML
def fromXML ( node : scala.xml.Node ) : TheThingIWant = new TheThingIWant {
val field = ( node \ "field" ). text
}