scala
without args is a Read-Eval-Print-Loop (REPL), similar to Scheme, Python, …
println("Hello, World!")
def fac(n: Int): BigInt = { if (n==0) 1 else n * fac(n - 1) }
{ val x = 5; x + 2 }
A "block" yields the value of the last expresseion
sbt
Simple Build Tool. Cf. make
, ant
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 to java ClassName
)
Hello, World!
()
not []
while (a(i) < pivot) i +=
1
for (i <- 0 until a.length) a(i) = util.Random.nextInt() % 100
val size = 20
scala inferred the type of size
as integer
val
assignment once only
for
generator filter yield
transformerExp
for { queens <- placeQueens(k - 1) column <- List.range(1, n + 1) if isSafe(column, queens, 1) } yield column :: queens
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) } }
object CallBackExAnonymous { def oncePerSecond(callback: () => Unit) { while (true) { callback(); Thread sleep 1000 } } def main(args: Array[String]) { oncePerSecond(() => println("time flies like an arrow...")) } }
timeFlies
removed
() => println("time flies like an arrow...")
is an anonymous
function
() => Unit
Unit cf. void
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.
if
-expression.
def <
, >
, …
Any
is the super-type of all (other) types.
object
v Java static
Boolean
, Int
, Long
, Float
, etc. are (built-in) classes/types.
break
s or continue
s in for
loops
_
, <-
, ::
(+ several more)
object
, Unit
, Any
, Nil
, None
, Some(x)
case
is used in different ways
Array
, List
var x, y, z: Int = 0
val x, y, z: Int = 0
assigned one-time
++
, or --
; use instead +=1
or -=1
val !#%&*+-/:<=>?@\^|~ = 1 // all simple opchars val wordEndingInOpChars_!#%&*+-/:<=>?@\^|~ = 1 val !^©® = 1 // opchars and symbols val abcαβγ_!^©® = 1 // mixing unicode letters and symbols
(x + y*2) / (1 + 3*z)
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
class Reference[T] { private var contents: T = _ def set(value: T) { contents = value } def get: T = contents }
false
for Boolean, ()
for the
Unit
type and null
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)) } }
List("one", "two", "three", "four").foreach { name => new Thread { override def run() = { println("Thread " + name + " [" + this + "] says Hello World!") } }.start }
List( "one", "two", "three", "four" ) . foreach { name => new Thread { override // needed def run() = { println( "Thread " + name + " [" + this + "] " + "says Hello, World!" ) } } . start }
recvActor ! msg
send a message msg to recvActor
def synchronized[A] (e: => A): A
Executes e
in mutex mode
def wait()
Running thread suspend itself by waiting on a
signal. (Unrelated to Linux signals.)
def wait(msec: Long)
As above, but waits at most msec
milli-seconds.
def notify()
Cooperate with a wait
-ing process, and check its
condition C
and inform. Even so, do while (!C) wait()
def notifyAll()
How many being waken up: one in notify()
and
all in notifyAll()
Many subtleties. Look up the docs.
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.
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
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 }
Any
is the super-type of all (other) types.
PartialFunction
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) } }
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
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
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
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 }
import scala.concurrent.ops._ val fut = future(someLengthyComputation) anotherLengthyComputation val y = f(fut()) + g(fut())
def future[A](p: => A): Unit => A = { val result = new SyncVar[A] fork { result.set(p) } (() => result.get) }
import scala.actors.Actor List("one", "two", "three", "four").foreach { name => new Actor { override def act() = { println("Thread " + name + " says Hello World!") } } .start }
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")!
% 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 of typer
.
% scalac -Xprint:all fileName.scala
Check it out!
scala
invokes java
with Scala's libraries.
scala
and scalac
are shell scripts on Linux. 200+ lines. Differ
in just one line. On windows, scala.bat
and scalac.bat
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.
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
classpath
example
% scalac -classpath /usr/share/java/scala-swing.jar HelloGui.scala
% scala -classpath .:/usr/share/java/scala-swing.jar HelloWorld
% 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[]); }