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
scala
without 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
sbt
Simple 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.scala
object HelloWorld { def main(args: Array[String]) { println("Hello, World!") } }
% scalac hello-world-println.scala
% ls -o
total 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 = 20
scala inferred the type ofsize
as integerval
assignment 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:
for
generator filteryield
transformerExp - 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
timeFlies
removed () => println("time flies like an arrow...")
is an anonymous function- Type inferred:
() => Unit
Unit 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" }
re
is 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
Any
is the super-type of all (other) types.
5 Scala cf. Java
- Scala
object
v Javastatic
Boolean
,Int
,Long
,Float
, etc. are (built-in) classes/types.- There are no
break
s orcontinue
s infor
loops
5.1 Tokens
- new special tokens:
_
,<-
,::
(+ several more) object
,Unit
,Any
,Nil
,None
,Some(x)
case
is used in different ways- Constructors:
Array
,List
var x, y, z: Int = 0
val x, y, z: Int = 0
assigned one-time- no
++
, or--
; use instead+=1
or-=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,
false
for Boolean,()
for theUnit
type andnull
for 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 ! msg
send a message msg to recvActor
6.4 Signals and Monitors
- Read: Andrews, Chapter 6: Monitors.
def synchronized[A] (e: => A): A
Executese
in 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 mostmsec
milli-seconds.def notify()
Cooperate with await
-ing process, and check its conditionC
and 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
Any
is 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 -help
Print a synopsis of options.% scalac -X
Print a synopsis of advanced options.% scalac -print pingObj-actor.scala
Print program with Scala-specific features removed.% scalac -Xprint:typer fileName.scala
Syntax trees at end oftyper
.% scalac -Xprint:all fileName.scala
Check it out!
8.3 Scala Misc Info
scala
invokesjava
with Scala's libraries.scala
andscalac
are shell scripts on Linux. 200+ lines. Differ in just one line. On windows,scala.bat
andscalac.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-RC3
alias scala=/usr/local/scala-2.11.0-RC3/bin/scala
alias scalac=/usr/local/scala-2.11.0-RC3/bin/scalac
PATH=$PATH:$SCALA_HOME/bin
- scala
classpath
example% 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\$.class
Compiled 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.