Transcript PowerPoint

A Pragmatic
Introduction to Scala
Magnus Madsen
Presenting Scala:
An alternative
to Java
Why I like Scala:
• object-orientated and functional
• elegant and concise
• unrestrictive – gives freedom of choice
Scala makes me a happier programmer!
Warning: Scala is the gateway drug to Haskell
A Playground for Fun Stuff:
• Engineering Perspective:
– Actor-based Programming
– Embedded DSLs, and more ...
• Research Perspective:
– Higher-Kinded Types
– Delimited Continuations
– Abstract Types, and more ...
A Used Car Analogy
class Car {
var frontRight: Wheel;
var frontLeft: Wheel;
var backRight: Wheel;
var backLeft: Wheel;
}
class Wheel {
...
}
Quote
[…] I can honestly say if someone had
shown me the Programming in Scala
book back in 2003 I'd probably have
never created Groovy.
James Strachan
(creator of Groovy)
Case Study: MiniTAJS
An inter-procedural dataflow analysis
– a scaled down version of TAJS
– has lots of cool stuff:
• abstract syntax trees, control flow graphs, etc.
• lattices, transfer functions, etc.
– about 4500 lines of code
• of which 90-95% are in functional style
Main.scala
package dk.brics.minitajs
object Main {
def main(args: Array[String]) {
val options = Options.read(args.toList)
Analysis.run(options)
}
}
Options.scala
case class Options(inputFile: File,
context: Boolean,
recency: Boolean,
lazyprop: Boolean,
...);
Case Classes: The bread and butter
• A case class declaration:
– case class Options(inputFile: File, ...)
• Automatically gives us:
– getters and setters
–
–
–
–
–
.equals() and .hashCode()
.toString()
.copy()
.apply()
.unapply()
Options.scala
object Options {
def read(args: List[String]): Options = {
val context = args.exists(_ == "--context");
val lazyprop = args.exists(_ == "--lazy");
...
Options(new File(args.last), context, recency, ...);
}
}
Bool.scala
abstract sealed class Bool {
def join(that: Bool): Bool = (this, that) match {
case (TrueBool, TrueBool) => TrueBool;
case (TrueBool, FalseBool) => AnyBool;
...
}
}
case object AnyBool extends Bool;
case object TrueBool extends Bool;
case object FalseBool extends Bool;
case object NotBool extends Bool;
Value.scala
case class Value(..., bool: Bool, undef: Undef, ...) {
def isMaybeTrue: Boolean = (bool eq TrueBool)
|| (bool eq AnyBool);
def joinUndef: Value
= copy(undef = undef.join(MaybeUndef));
}
LatticeOps.scala
abstract class LatticeOps(...) extends ContextMixin
with RecencyMixin
with PropagationMixin
trait PropagationMixin {
def propagate(state: BlockState, info: PropagateInfo,
lattice: Lattice): Lattice;
}
new LatticeOps(...) with CallSensitivity
with RecencyAbstraction
with LazyPropagation
Arguments
Arguments
Problem: In functional programming argument
lists grow and grow
Solution: Wrap arguments up inside a data type.
In Scala this translates to a case class.
Example
def propagate(state: BlockState,
sourceContext: Context,
sourceBlock: BasicBlock,
targetContext: Context,
targetBlock: BasicBlock,
lattice: Lattice): Lattice
def propagate(state: BlockState,
info: PropagateInfo,
lattice: Lattice): Lattice
def propagate(s: BlockState, i: PropagateInfo,
l: Lattice): Lattice = {
lattice.getState(i.targetContext, i.targetBlock) match {
case Reachable(targetState) => {
if (state != targetState) {
Mutability!
queue.enqueue(i.targetContext, i.targetBlock);
}
lattice.putState(i.targetContext, i.targetBlock,
targetState.join(s));
}
case Unreachable => {
queue.enqueue(i.targetContext, i.targetBlock);
lattice.putState(i.targetContext, i.targetBlock, s);
}
}
}
Limited Mutability
Problem: Whenever new flow enters a
basicblock it must be added to the solver queue
Potential Solution: We could modify all
functions to return a pair where the last
component is the set of basicblocks that must
be enqueued
But the stack is deep
Solver.Solve ->
BlockTransfer.transfer ->
BlockTransfer.transferCallBlock ->
LatticeOps.functionEntry ->
LazyPropagation.functionEntry ->
LazyPropagation.propagate
• Not feasible to modify all return types
• Instead we use a mutable queue!
But the stack is still deep!
How do we get a reference to the queue???
– We could use a global reference
Or we could use Scala's implicits:
class BlockTransfer(...)(implicit q: Queue)
class LatticeOps(...)(implicit q: Queue)
Scaladoc
Some of the Bad Stuff
•
•
•
•
Death Traps
Debugging
Compiler Warnings
Compilation Times
Death Trap
case class BasicBlock(var successors: Set[BasicBlock]);
val a = BasicBlock(Set.empty);
a.succesors = Set(a);
a == a;
Difficult to Debug
Cryptic Compiler Warnings
Compilation is Slow
• Compiling miniTAJS takes 35 seconds
– 4500 lines of code
– 113 classes + 40 objects = 580 .class files
• Why?
– Scalac is written in Scala - i.e. it runs on the JVM
– Scalac must type-check both Java and Scala
– Scalac must do local type inference
Functions + Objects
Does it work?
No, not really
(but...)
Functions + Objects
• Fundamental problem:
– Functional Programming = Immutability
– Object-orientated Programming = Mutability
• Immutable objects are not really objects
• Mutating functions are not really functions
Functions + Objects
A proposed solution:
1. Split the program into FP and OO parts
2. Decide whether some data should be
immutable or mutable (i.e. targed for FP or
OO programming)
3. Prefer immutable data, otherwise use
mutable data
Not a silver bullet
Recent History
•
•
•
•
Scala 2.10 Milestone 1 (Januar 2012)
New Eclipse Plugin (January 2012)
New IntelliJ IDEA Plugin (December 2011)
Scala 2.9 (May 2011)
– parallel collections
• Scala 2.8 (July 2010)
– new collections framework
Critical Mass?
• Introduction to the Art of Programming Using Scala
(October 2012)
• Scala for the Impatient (March 2012)
• Scala in Action (April 2012)
• Scala in Depth (April 2012)
• Actors in Scala (Januar 2012)
• Pro Scala: Monadic Design Patterns for the Web
(August 2011)
• Programming in Scala 2nd (Januar 2011)
Recommended Books
Recommended Websites
• Official Scala website
– http://scala-lang.org/
• Daily Scala – small code sniplets
– http://daily-scala.blogspot.com/
• CodeCommit – "Scala for Java Refugees"
– http://www.codecommit.com/blog/
• StackOverflow
– http://stackoverflow.com/
Summary
is viable alternative to Java
– object-orientated and functional
– has useful features not found in Java
– runs on the JVM and interacts with Java
– is fun!
Thank You!
(now go download Scala)
Addendum
Me>
Erik>
Me>
I need [what turns out to be virtual types]
You could use an extra-linguistic solution
What do you mean "extra-linguistic"?
Erik>
A perl script...
Last Code Slide: Real Code
Embedded DSLs
Scala has syntactic flexibility:
object Button {
def onClick(f: => Unit) { ... }
}
Button.onClick(() => println("Hello"!));
But you can also write:
Button.onClick {
println("Hello");
}
Historical Anecdote
BETA was supposed to be called Scala:
For many years the name SCALA was a candidate for
a new name – SCALA could mean SCAndinavian
LAnguage, and in Latin it means ladder and could be
interpreted as meaning something ‘going up’.
The When, Why and Why Not
of the BETA Programming Language