A Practical Intro to Scala
Table of Contents
1 75 minutes or less?
- Obviously, in 75 minutes or less, we cannot make you an expert in
Scala. But you will learn enough Scala to start writing programs
involving actors – provided you
- have taken an OS course, and
- are fluent in Java.
- However, we defocus functional programming, and fancy features.
- Link to Source Code Examples: ./scalaExamples
- Martin Odersky and others, at EPFL, Switzerland, are the designers of Scala.
- Scala is still evolving: v 2.11.6 Mar 2015
2 Scala REPL interactive
scalawithout args is a Read-Eval-Print-Loop (REPL), similar to Scheme, Python, …- Try
println("Hello, World!") - Try
def fac(n: Int): BigInt = { if (n==0) 1 else n * fac(n - 1) } - Note the declaration style; the {} can be omitted
- Try
{ val x = 5; x + 2 }A "block" yields the value of the last expresseion - Caution: Scala is a large language; a simple mistake can produce difficult to understand error.
3 Scala Tools
sbtSimple Build Tool. Cf.make,ant- Intellij IDEA plugin http://www.jetbrains.com/idea/features/scala.html
- Eclipse plugin http://scala-ide.org/
- http://www.scalatest.org/
3.1 scalac followed by scala
- content of file named
hello-world-println.scalaobject HelloWorld { def main(args: Array[String]) { println("Hello, World!") } } % scalac hello-world-println.scala% ls -ototal 16 -rw-rw-r-- 1 pmateti 595 Mar 29 21:26 HelloWorld.class -rw-rw-r-- 1 pmateti 608 Mar 29 21:26 HelloWorld$.class -rw-rw-r-- 1 pmateti 90 Mar 29 21:21 hello-world-println.scala
% scala HelloWorld(similar tojava ClassName)Hello, World!
4 Short Examples
4.1 Quick Sort (Layout of a Complete Prog)
- array indexing
()not [] - while loop:
while (a(i) < pivot) i +=1 - for loop:
for (i <- 0 until a.length) a(i) = util.Random.nextInt() % 100
val size = 20scala inferred the type ofsizeas integervalassignment once only- source code ./scalaExamples/quickSort.scala
4.2 The N-Queens Problem (For-Comprehensions)
- 8-queens problem: Given a standard chess-board, place 8 queens so that no queen is in check from any other.
- For-Comprehensions stx:
forgenerator filteryieldtransformerExp - For-Comprehensions
for { queens <- placeQueens(k - 1) column <- List.range(1, n + 1) if isSafe(column, queens, 1) } yield column :: queens - source code ./scalaExamples/nqueens.scala
4.3 CallBack
object CallBackEx {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def timeFlies() {
println("time flies like an arrow...")
}
def main(args: Array[String]) {
oncePerSecond(timeFlies)
}
}
4.4 CallBack, Anonymous
object CallBackExAnonymous {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def main(args: Array[String]) {
oncePerSecond(() =>
println("time flies like an arrow..."))
}
}
- Note
timeFliesremoved () => println("time flies like an arrow...")is an anonymous function- Type inferred:
() => UnitUnit cf. void
4.5 Classes, Inheritance and Overriding
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
override def toString() =
"" + re + (if (im < 0) "" else "+") + im + "i"
}
reis a getter method with no arguments; parens omittable.- Note the embedded
if-expression.
4.6 Traits
- Java has just single inheritance, and so uses multiple interfaces.
- Scala Traits are "partial" classes; they contain code for methods.
- A Scala class can import code from several traits.
- source code ./scalaExamples/traitEx.scala
- source code ./scalaExamples/compare.scala ;
def <,>, … - type
Anyis the super-type of all (other) types.
5 Scala cf. Java
- Scala
objectv Javastatic Boolean,Int,Long,Float, etc. are (built-in) classes/types.- There are no
breaks orcontinues inforloops
5.1 Tokens
- new special tokens:
_,<-,::(+ several more) object,Unit,Any,Nil,None,Some(x)caseis used in different ways- Constructors:
Array,List var x, y, z: Int = 0val x, y, z: Int = 0assigned one-time- no
++, or--; use instead+=1or-=1
5.1.1 Tokens-2
- Alphanumeric identifiers, Operator identifiers, Mixed identifiers
- (from stackOverFlow.com ) Here are some valid examples:
val !#%&*+-/:<=>?@\^|~ = 1 // all simple opchars val wordEndingInOpChars_!#%&*+-/:<=>?@\^|~ = 1 val !^©® = 1 // opchars and symbols val abcαβγ_!^©® = 1 // mixing unicode letters and symbols
5.2 Case Classes and Pattern Matching
- Example expression:
(x + y*2) / (1 + 3*z) - Develop a tree representation for use in a Calc program.
abstract class Tree case class Sum(l: Tree, r: Tree) extends Tree case class Var(n: String) extends Tree case class Const(v: Int) extends Tree
- ./scalaExamples/calc.scala source code for a complete program but without * and /
5.3 Genericity
- Genericity is the ability to write code where types can be substituted.
class Reference[T] { private var contents: T = _ def set(value: T) { contents = value } def get: T = contents }- Here, the underscore stands for the default value (of type T).
This default is 0 for numerics,
falsefor Boolean,()for theUnittype andnullfor all object types. object IntegerReference { def main(args: Array[String]) { val cell = new Reference[Int] cell.set(13) println("Reference contains the half of " + (cell.get * 2)) } }- source code: ./scalaExamples/generics.scala
6 Concurrency in Scala
6.1 Threads
- Try this in scala REPL:
List("one", "two", "three", "four").foreach { name => new Thread { override def run() = { println("Thread " + name + " [" + this + "] says Hello World!") } }.start } - Next: same code as above but prettied up
6.2 Thread Example, prettied up
List( "one", "two", "three", "four" ) .
foreach {
name =>
new Thread {
override // needed
def run() = {
println(
"Thread " + name +
" [" + this + "] " +
"says Hello, World!"
)
}
}
. start
}
6.3 Concurrency in Scala
- Scala can do Signals and Monitors, SyncVars, Futures, Parallel Computations, Semaphores, Readers/Writers, Asynchronous Channels, Synchronous Channels, Threads, Workers, Mailboxes, and Actors.
recvActor ! msgsend a message msg to recvActor
6.4 Signals and Monitors
- Read: Andrews, Chapter 6: Monitors.
def synchronized[A] (e: => A): AExecutesein mutex modedef wait()Running thread suspend itself by waiting on a signal. (Unrelated to Linux signals.)def wait(msec: Long)As above, but waits at mostmsecmilli-seconds.def notify()Cooperate with await-ing process, and check its conditionCand inform. Even so, dowhile (!C) wait()def notifyAll()How many being waken up: one innotify()and all innotifyAll()Many subtleties. Look up the docs.
6.5 Semaphores
package scala.concurrent
class Lock {
var available = true
def acquire = synchronized {
while (!available) wait()
available = false
}
def release = synchronized {
available = true
notify()
}
}
Similar to our CEG 7370 Official Binary Semaphores (but not exactly). The above is implemented using a monitor.
6.6 Bounded Buffers / Producers-Consumers
class BoundedBuffer(N: Int) {
val buf = new Array[Int](N)
var in, out = 0 // indices of buf
var n = 0 // #items in buf
def put(x: Int) = synchronized {
while (n >= N) { println("buf full") ; wait() }
buf(in) = x ; in = (in + 1) % N ; n += 1
if (n == 1) notifyAll() }
def get: Int = synchronized {
while (n == 0) wait()
val x = buf(out) ; out = (out + 1) % N ; n -= 1
if (n == N - 1) notifyAll()
x }
}
complete source: ./scalaExamples/bounded-buffers.scala
6.7 Mailboxes
class MailBox {
def send(msg: Any) synchronized { ... }
def receive[A](f: PartialFunction[Any, A]): A // uses synchronized { ... }
def receiveWithin[A](msec: Long)(f: PartialFunction[Any, A]): A
}
- type
Anyis the super-type of all (other) types. PartialFunction
6.8 Readers/Writers
class ReadersWriters {
val m = new MailBox
private case class Writers(n: Int) { m send this }
private case class Readers(n: Int) { m send this }
Writers(0); Readers(0)
// see slide (down-arrow) also
def endRead = m receive { // dot omitted
case Readers(n) => Readers(n-1)
}
def endWrite = m receive {
case Writers(n) => Writers(n-1)
if (n == 0) Readers(0)
}
}
6.8.1 Readers/Writers, contd
def startRead = m receive {
case Writers(n) if n == 0 => m receive {
case Readers(n) => Writers(0); Readers(n+1)
}
}
def startWrite = m receive {
case Writers(n) =>
Writers(n+1)
m receive { case Readers(n) if n == 0 => }
}
TBD URL to CEG 7370 Readers/Writers with priority for writers
6.9 Asynchronous Channels
class Channel[A] {
private var written = new LinkedList[A]
private var lastWritten = written
private var nreaders = 0
def write(x: A) = synchronized {
lastWritten.elem = x
lastWritten.next = new LinkedList[A]
lastWritten = lastWritten.next
if (nreaders > 0) notify() }
def read: A = synchronized {
if (written.next == null) {
nreaders += 1; wait(); nreaders -= 1
}
val x = written.elem
written = written.next
x }
}
API scala.concurrent.package; cf. CEG 7370 Semi AMP
6.10 Synchronous Channels
class SyncChannel[A] {
private var data: A = _
private var reading = false
private var writing = false
def write(x: A) = synchronized {
while (writing) wait()
data = x
writing = true
if (reading) notifyAll()
else while (!reading) wait()
}
def read: A = synchronized {
while (reading) wait()
reading = true
while (!writing) wait()
val x = data
writing = false
reading = false
notifyAll()
x
}
}
API scala.concurrent.package; cf. CEG 7370 SMP
6.11 SyncVars
package scala.concurrent
class SyncVar[A] {
private var isDefined: Boolean = false
private var v: A = _
def get = synchronized
{while (!isDefined) wait(); v}
def set(x: A) = synchronized
{v = x; isDefined=true; notifyAll()}
def isSet: Boolean = synchronized {isDefined}
def unset = synchronized {isDefined = false} // API
}
6.12 Futures
- An expression yet to be computed. In parallel with something else.
- Use
import scala.concurrent.ops._ val fut = future(someLengthyComputation) anotherLengthyComputation val y = f(fut()) + g(fut())
- API Futures
def future[A](p: => A): Unit => A = { val result = new SyncVar[A] fork { result.set(p) } (() => result.get) } - More on futures in akka
6.13 Hello Word with Actors
7 Scala can be Hard to Learn
- Voluminous documentation aimed at programming newbies. Too many (incompatible) versions. 24,066 questions tagged on http://stackoverflow.com/questions/tagged/scala
- Functional Programming paradigm: Imagine no variable can be assigned more than once. Anonymous Functions. Currying. Closures. Functions as first class values. Lazy values.
- Futures, Promises
- Type inferance; Co-variance and contra-variance; Monads
- Omission of "things": Implicit arguments, the dot, the semicolon, …
8 scala, scalac details
8.1 Execute External Program
import scala.sys.process._
val cmd = "/usr/local/scala-2.11.0-RC3/bin/scalac -help"
val txt = cmd.!! // captures stdout
val i : Int = Process("ls -l")!
8.2 scalac options
% scalac -helpPrint a synopsis of options.% scalac -XPrint a synopsis of advanced options.% scalac -print pingObj-actor.scalaPrint program with Scala-specific features removed.% scalac -Xprint:typer fileName.scalaSyntax trees at end oftyper.% scalac -Xprint:all fileName.scalaCheck it out!
8.3 Scala Misc Info
scalainvokesjavawith Scala's libraries.scalaandscalacare shell scripts on Linux. 200+ lines. Differ in just one line. On windows,scala.batandscalac.bat- Scala version I am using [date: Mar 30, 2014] is
Welcome to Scala version 2.11.0-RC3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0). Type in expressions to have them evaluated. Type :help for more information.
8.4 Scala Misc Info-2
- bash:
export SCALA_HOME=/usr/local/scala-2.11.0-RC3alias scala=/usr/local/scala-2.11.0-RC3/bin/scalaalias scalac=/usr/local/scala-2.11.0-RC3/bin/scalacPATH=$PATH:$SCALA_HOME/bin
- scala
classpathexample% scalac -classpath /usr/share/java/scala-swing.jar HelloGui.scala% scala -classpath .:/usr/share/java/scala-swing.jar HelloWorld
8.5 Disassembly with javap
% javap HelloWorld.class HelloWorld\$.classCompiled from "hello-world-println.scala" public final class HelloWorld { public static void main(java.lang.String[]); } Compiled from "hello-world-println.scala" public final class HelloWorld$ { public static final HelloWorld$ MODULE$; public static {}; public void main(java.lang.String[]); }
9 References
- Link to Source Code Examples: ./scalaExamples
- https://typesafe.com/activator is the place for ready-to-compile -and-run examples of Scala (or Java) with Akka. Required Visit.
- Martin Odersky, "Scala by Example". A book by the designer of the language. Highly recommended read: Chapter 17: Abstractions for Concurrency (10+ pages). The full book is at http://www.scala-lang.org/docu/files/ScalaByExample.pdf, 150+ pages. June 2014. Despite the name of the book, only a few were ready-to-compile-and-run examples. Some of my slides are based on this book. Recommended Reading.
- Lewis, Laufer, and Thiruvathukal, "SIGCSE Workshop on Scala", March 2014, http://scalaworkshop.cs.luc.edu/latex/sigcse-scala.pdf; SIGCSE = ACM Special Interest Group on Computer Science Education. http://www.sigcse.org/ Recommended Reading.
9.1 References, contd
- Horstmann, Cay S. "Scala for the Impatient." Pearson Education, 2012. A legit pdf of the first 100+ pages is widely downloadable. "Currently the best compact introduction to Scala" – Martin Odersky. Recommended Reading.
- Martin Odersky, https://www.coursera.org/courses?search=scala The "Principles of Reactive Programming" is relevant to this course.
- Michel Schinz, Philipp Haller, "A Scala Tutorial for Java programmers", http://www.scala-lang.org/docu/files/ScalaTutorial.pdf, 2014, 15 pages. Some of my examples are from this booklet. Recommended Reading.
- Peter Sestoft, "Programs as Data; The Scala language, an overview", slides, Univ of Copenhagen, 2013. Some of my slides are adapted from here.
- Opinions: http://www.unlimitednovelty.com/2009/04/why-i-dont-like-scala.html; http://zeroturnaround.com/rebellabs/scala-sink-or-swim-part-1/ What to avoid in the Scala ecosystem. Do visit – after you learn enough Scala and Akka.