Scala in breve

Sito di riferimento: http://scala-lang.org

Programmazione funzionale

  • functions are first-class values
  • immutable data, no side effects

Variabili

var x = 1 //mutabile
val x = 1 //immutabile
val s = "foo" //tipo implicito
val i:Int = 1 //tipo esplicito

Cicli

while (i < foo) {
println(i)
} 

do {
// stuff
} while (condition)

for (arg <- args) println(arg)
for (i <- 0 to 5) println(i)
for (i <- 0 until 10 by 2)
        println(i)

for (
        file <- files
        if file.isFile
        if file.getName.endsWith(".a")
) doSomething(file)

args.foreach(arg => println(arg))
args.foreach(println(_))
args.foreach(println)

Strutture di controllo

if (a == b) foo()
if (a == b) foo else bar
if (a == b) {
        foo
} else if (a == c) {
        bar
} else {
        baz
}


"==" is not reference equality

foo match {
        case "a" => doA()
        case "b" => doB()
        case _ => doDefault
}

Funzioni

  • functions return last value computed by method
  • if name ends in '', invoke on right operand
  • '+' is a method on Int, String
  • apply(), update()
def hello(s: String): Unit = {
        println("Hello " + s)
}

def hello: Unit = println("Hello")
def hello = println("Hello")
// not recommended
def hello { println("Hello") }

// variable length args
def foo(args: String*) = {
        args.foreach(...)

// named args
point(x=10, y=20)

// can call without a dot or parens if
// it takes only one param
var x = f.add(10)
var x = f add 10

// function literal syntax
(x: Int, y:Int) => x + y

Tipi di dati

val names = Array("Al", "Bob")
val names = new Array[String](5)
val names = Map(99676 -> "AK")

val names = List("Al", "Bob")
val names2 = "Joe" :: names

// tuples
val things = (100, "Foo")
println(things._1)
println(things._2)

Collections

Sequence, List, Array, ListBuffer,ArrayBuffer, StringOps, Set, Map,TreeSet, Stream, Vector, Stack,Queue, Range, BitSet, ListMap, more

  • Tuples can hold different objects
  • Mutable and immutable collections
  • traits: Traversable, Iterable, Seq,IndexedSeq, LinearSeq, Buffer

try, catch, finally

try {
        something
} catch {
        case ex: IOException => // handle
        case ex: FileNotFoundException =>// handle
} finally { doStuff }

Classi ed Oggetti

package foo.bar

import java.io.File
import java.io._
import java.io.{Foo, File => Bar}


class A { ... }
class A (s: String) { ... }
class A (val s: String) { ... }
class A (private val s: String) { ... }
class A (var s: String) { ... }

class Person (s: String) {
        require(name != "Joe")
        val name: String = s
        private val a = "foo"
}

class Bird extends Animal with Wings {
        override val foo = true
}

// singleton objects
object Foo {
        def main(args: Array[String]) = {
        args.foreach(println)
        }
}

object Bob extends Person { ... }


// abstract class
abstract class Person {
        // method with no implementation
        def walk: Unit
}

class Employee(name: String)extends Person {
        ...
}

// sealed class - no new subclasses
// unless defined in current file
sealed sbstract class Foo { ... }
case class Bar(s: String) extends Foo

Tratti

traits like class except:

  • no class params
  • super dynamically bound
trait Talks {
        def speak() {
        println(“Yada yada yada...”)
        }
}

class A { ... }
trait T1 { ... }
trait T2 { ... }
class B extends T1 { ... }
class C extends A with T1 with T2

Script

println(args(0))
println(args.toList)
args.foreach(println)
scala foo.scala

#!/bin/sh
exec scala "$0" "$@"
!#
object Hello {
        def main(args: Array[String]) {
                args.foreach(println)
        }
}


// Application trait
object Hello extends Application {
        args.foreach(println)
}

Underscore

"think of _ as a blank that needsto be filled in"

strings.map(_.toUpperCase())
(1 to 10).map(_*2)

args.foreach(println(_))
args.foreach(println)

numbers.filter(_ < 10)

// for each element in the array
println(array: _*)

case classes

scala adds syntactic conveniences:

  • adds a factory method with the name of your class
  • all args in param list implicitly get
  • val, and become fields
  • add implementations of toString,hashCode, and equals
  • adds a copy method
abstract class Expr
case class Var(name: String) extends Expr
case class Num(num: Double) extends Expr

val v = Var("x")
v.name
println(v) //shows toString
//'==' works
v.copy

case, match

selector match choices , "_" is the wildcard pattern

def f(x: Int): String = x match {
        case 1|2|3 => "1-2-3"
        // default
        case _ => "huh?"
}

def f(x: Any): String = x match {
        case 1 => "one"
        case "2" => "two"
        // typed pattern
        case i:Int => "got an int"
        case s:String => "got a string"
        case _ => // do nothing
}

pattern matching:

  • constant pattern ("a", 10)
  • variable pattern (x)
  • wildcard pattern (_)
  • constructor pattern ( Foo("-", e) )
  • typed pattern (see above)

isInstanceOf and asInstanceOf are discouraged

actors

import scala.actors._
object Foo extends Actor {
        def act() {
        // your logic here
        }
}

import scala.actors.Actor._
val hiActor = actor {
        while(true) {
                receive {
                case msg =>
                        // your logic
                }
        }
}

object Foo extends Actor {
def act() {
                react {
                        case ...
                }
        }
}

// send message
hiActor ! "hello"

Note:

  • share-nothing, message-passing model
  • receive, receiveWithin
  • react is more efficient
  • don't block when processing messages (helper actor)
  • prefer immutable messages
  • make messages self-contained

e molto altro

// type alias
type D = Double

// anonymous function
(x:D) => x + x

// lisp cons
var x = 1 :: List(2,3)

var(a,b,c) = (1,2,3)
val x = List.range(0,20)