scala at huji pl seminar 2008
Post on 06-May-2015
1.530 Views
Preview:
TRANSCRIPT
Introduction to Scala Introduction to Scala programming languageprogramming language
Yardena MeymannJune 2008
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
Java Virtual MachineJava Virtual Machine
Java ArchitectureJava ArchitectureHelloWorld.java
HelloWorld.class
javac
Native OSNative OS
HotSpot
load class
Class Loader
Bytecode Executor JITcompiler
Java Libraries
interpret execute
Garbage Collector
Java Virtual MachineJava Virtual Machine
Java as a PlatformJava as a Platform
HelloWorld.****
HelloWorld.class
****c
load class
Class Loader
Java Libraries
...
Garbage Collector
JVM LanguagesJVM Languages
● Scala● Groovy● BeanShell● JavaFX Script● ...
● JRuby● Jython ● Rhino Javascript● Kawa Scheme● Clojure Lisp● hundreds of others...
Why JVM?Why JVM?● Most popular VM in the world● Multi-platform● Free● Mature● Secure and reliable● Fast
can outperform native code compiled with GCC● Management and monitoring capabilities● Has a specification
– multiple vendor and open source implementations
Why Scala?Why Scala?● Object oriented and functional● Statically typed● High performance● High interoperability with Java● Advanced type system● Advanced concurrency model● Support for modularity and extensibility● Built-in XML support
M. Odersky
1995
GJ1999
J. Gosling1991
Java and Scala HistoryJava and Scala History
Java announced,
first beta release1995
Java 1.0
1996Java 1.3
2000
1999
work on Scala starts2001
Java 1.42002
Java 1.5(Tiger)2004
Java 1.6(Mustang)
2006
1.0 2003 2.0 2006
Java 1.1
1997
Java 1.21998
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
Hello ScalaHello Scala
object HelloWorld extends Application {
println("Hello, world!")
}
object HelloWorld {
def main(args: Array[String]) =
System.out.println("Hello, world!")
}
: Unit =
● object = singleton class
● optional semicolon
● def● implicit public
● type after name, optional
● generics using [ ]● unit = void● calling into java.lang
library
● different constructor syntax
Simple GreetingSimple Greeting
def main(args:Array[String]) = {
val size = args.length
println("Greeting " + size + " members:")
var greeting = "Hello "
for (i <- 0 until args.length) {
greeting += (args(i) + ",")
}
if (args.length > 0) greeting = greeting.substring(0, greeting.length – 1)
greeting += "!"
println(greeting);
}
immutable variabletype int inferred
mutable variabletype String
inferredint is an object,
alternative method invocation syntax
Java-like loop
if statement
array element access
Simple TimerSimple Timerobject SimpleTimer {
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)
}
}
function type
functions are objects
Reusable TimerReusable Timer
object Timer {
def periodicCall(seconds: Int, callback: () => unit) = {
while (true) { callback(); Thread.sleep(seconds * 1000) }
}
def main(args: Array[String]) = {
periodicCall(1, () => println("time flies..."))
}
}anonymous function
Better GreetingBetter Greetingdef main(args:Array[String]) = {
val size = args.length
println("Greeting " + size + " members:")
var greeting = "Hello "
for (i <- 0 until args.length) {
greeting += (args(i) + ",")
}
if (args.length > 0) greeting = greeting.substring(0, greeting.length – 1)
greeting += "!"
println(greeting);
}
args.foreach(arg => greeting += (arg + " "))
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
TuplesTuples
def divmod(x: int, y: int) = (x / y, x % y)val z = divmod(x, y)println("quotient: " + z._1 + ", rest: " + z._2)
The actual type of a tuple depends upon the number and of elements it contains and the types of those elements.
The type of (99, "Luftballons") is Tuple2[Int, String].
The type of ('u', 'r', "the", 1, 4, "me") is Tuple6[Char, Char, String, Int, Int, String]
MapMap val treasureMap = new HashMap[Int, String] treasureMap += 1 -> "Go to island." treasureMap += 2 -> "Find big X on ground." treasureMap += 3 -> "Dig." println(treasureMap(2))
val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
println(romanNumeral(4))
When we say 1 -> "Go to island.", we are actually calling a method named -> on an Int with the value 1, and passing in a String with the value "Go to island." This -> method, which you can invoke on any object in a Scala program, returns a two-element tuple containing the key and value.
ComprehensionsComprehensions
val names = "Ted Neward" :: "Neal Ford" :: "Scott Davis" :: "Venkat Subramaniam" :: "David Geary" :: Nil
val longFirstNames = for { name <- names firstName = name.substring(0, name.indexOf(' ')) if firstName.length > 4
} yield firstName
val filesHere = (new java.io.File(".")).listFiles for ( file <- filesHere; if file.isFile; if file.getName.endsWith(".scala") ) println("Found " + file)
Types with no typing!Types with no typing!
Comprehensions definedComprehensions defined
Example: for (val p ← persons; p.age > 20) yield p.nameGenerally, a for-comprehension is of the form
for ( s ) yield es is a sequence of generators, definitions and filters
generator is of the form val x ← e,where e is a list-valued expression; it binds x to successive values in the list
definition is of the form val x = e; it introduces x as a name for the value of e in the rest of the comprehension
filter is an expression f of type boolean; it omits from consideration all bindings for which f is false
Scala QuickSort
Comprehensions make Comprehensions make programs short and clearprograms short and clear
Java QuickSort
Basic pattern matchingBasic pattern matching
Scala case statements can’t “overlap” causing multiple matches
Match statement returns whatever value is returned from the matched case statement
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
Everything is an objectEverything is an object
● Scala uses a pure object-oriented model similar to Smalltalk: every value is an object and every operation is a message send.
● Every class in Scala inherits from scala.Any● The classes fall into two categories:
– value classes inherit from scala.AnyVal and – reference classes inherit from scala.AnyRef
Scala type hierarchyScala type hierarchy
Null and NothingNull and Nothing
● Type Null is a subtype of all reference types; its only instance is the null reference. Since Null is not a subtype of value types, null is not a
member of any such type. For instance, it is not possible to assign null to a variable of type int.
● Type Nothing is a subtype of every other type; there exist no instances of this type. For instance, the Scala library defines a value Nil of type List[Nothing]. Because lists are covariant in Scala, this makes Nil an instance of List[T], for any element type T.
Object basicsObject basics
● Properties● Constructors● Constructor properties● Abstract methods● Override methods
Simple property andSimple property anddefault constructordefault constructor
Java:
public class Person {
private String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Scala:
class Person {
var name: String
}
...
println(person.name)
public Person(String name) { this.name = name; }
class Person (var name: String)
Constructors, operators, Constructors, operators, overriding methodsoverriding methods
class Rational(n:Int, d:Int) { private def gcd(x:Int, y:Int): Int = { ...//greatest common denominator } private val g = gcd(n,d) val numer:Int = n/g val denom:Int = d/g def this(n:Int) = { this(n, 1) } def +(that:Rational) = new Rational(numer*that.denom + that.numer*denom, denom * that.denom) def -(that:Rational) = ... def *(that:Rational) = ... def /(that:Rational) = ... override def toString() = "Rational: [" + numer + " / " + denom + "]"}
Default constructor
Alternative constructor; must call the default constructor
Object initialization uses constructor properties,
read-only properties defined
Operators defined
Override method – override modifier is mandatory
Abstract classAbstract class
abstract class Shape { var fillColor:Color = null def draw(g:Graphics):Unit def area:Double}
Abstract methods
Property
SubclassesSubclassesclass Circle(var radius:Int) extends Shape {
def draw(g:Graphics):Unit = {
if (fillColor == null) {
g.drawOval(0, 0, radius / 2, radius / 2)
} else {
g.setColor(fillColor);
g.fillOval(0, 0, radius / 2, radius / 2)
}
}
def area:Double = {
var back = Math.Pi * radius
back * radius
}
}
class Square(var width:Int) extends Shape {
def draw(g:Graphics):Unit = {
if (fillColor == null) {
g.drawRect(0, 0, width, width)
} else {
g.setColor(fillColor)
g.fillRect(0, 0, width, width)
}
}
def area:Double = width * width
}
Advanced PropertiesAdvanced Properties
Effectively, all public variables are instance properties.
To override mutator and accessor behavior:_= method suffix
syntax allows to redefine the assignment operator for a variable
Simulating a Java BeanSimulating a Java Bean
class Person(fn:String, ln:String, a:Int) { @scala.reflect.BeanProperty var firstName = fn @scala.reflect.BeanProperty var lastName = ln @scala.reflect.BeanProperty var age = a
override def toString = "[Person firstName:" + firstName + " lastName:"
+ lastName + " age:" + age + " ]"}
More on MethodsMore on Methods● Protected and private, packages
– public by default– protected and private modifiers supported
– private[<package name>] enhanced “package protected” - applies to one of the containing packages of current method
● Returning from method
– return statement is optional: the last statement in an expression, be it a scope, a closure or a method becomes its return value.
– If method can return at different points in the execution flow, return type must be specified
● Repeated parameters (var-args) - <method>(...,<arg>*)● Method reference
– call without parameters or prefix with &
Advanced ObjectsAdvanced Objects
● Singletons and companions● Object as a function● Case classes● Sealed classes● Traits and mix-in class composition● Implicit conversions (views)● More...
Singleton classes and Singleton classes and pseudo-static methodspseudo-static methods
● class vs. object (Singleton design pattern)● companions
object Person { //companion module def createPerson() = new Person()}class Person { //companion class def name() = "Daniel"}
Function ObjectFunction Object
Function object has one or more apply methods:
Doug Pardee
val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
Together with companion object feature, it is used to facilitate the Factory Method design pattern, as we saw in previous Map example:
object Square { def apply(in: double) = in * in def apply(in: float) = in * in def apply(in: int) = in * in} val xSquared = Square(x)
ADTs Using Case ClassADTs Using Case Class
● Case classes export their constructor parameters and provide a recursive decomposition mechanism via pattern matching. The constructor parameters of case classes are treated as public values and can be accessed directly.
● The new keyword is optional for instance creation.
case class ClockTime (hour: Int, min: Int) is a valid case class definition. ClockTime(10,30) creates an instance.
It makes only sense to define case classes if pattern matching is used to decompose data structures.
Case Class - ExampleCase Class - Example
The output will look something like this:Red: 100Blue: 220R: 100, G: 200, B: 50Invalid color
Another Case ClassAnother Case Class
Set of definitions for binary tree:
In-order traversal of binary tree:
Case classes definedCase classes defined
● All lower-case identifiers in the pattern will bind the decomposed value and are available on the right-hand side of the pattern.
● Order is important: a first-match policy is used.
● Constant values can be used in patterns to restrict matching case ClockTime(10, min) will only match any time in the 10th hour (and bind minutes to min)
● Richer conditions can be defined with guards.
– case ClockTime(hour, min) if hour > min● When no pattern matches a value, the match statement throws a
MatchError.
● A default case can be added, using the wild-card pattern. case _ will match any value.
Exception handlingException handling
Exception handling uses “almost Java” syntax with pattern match on exception type within the catch clause.
Side note: Scala does not have checked exceptions, in contrast to Java.
Sealed classesSealed classes
Sealed classes are defined using the sealed modifier.A sealed class may not be directly inherited, except if the
inheriting template is defined in the same source file as the inherited class*.
In case of pattern match on sealed class, the compilation will emit warnings if the set of patterns is not exhaustive (MatchError might be raised at run-time)
Traits and Traits and Mixin Class CompositionMixin Class Composition
● Trait is a special kind of class defined using trait keyword● Traits are like Java interfaces, but can define default
implementations for methods in the trait. A class can incorporate as many traits as desired using with keyword, accumulating their implementations.
● A trait can be inherited– when defining a class
class JamesBondsCar extends Car with Flying with Diving– or when creating an instance
val jbsCar = new Car with Flying with Diving
Traits - ExampleTraits - Example
Traits – more detailsTraits – more details● There must be a common parent class with the
inherited● When multiple traits are inherited
– they can refer to members of their common super class,– but not to members of other mixed-in traits.
● A trait can require another class or trait; it can only be mixed-in when the requirement is available.trait Reading extends Person requires Seeingtrait Reading extends Person { self: Seeing => ... }
● In contrast to classes, traits may not have constructor parameters.
trait Base { type exp <: Exp; trait Exp { def eval: int } class Num(v: int) extends Exp { val value = v; def eval = value }}
Mixins Mixins He who defs last, defs bestHe who defs last, defs best
The order in which traits are mixed-in determines overriding strategy
“Expression problem” example:
trait Show extends Base { type exp <: Exp; trait Exp extends super.Exp { def show: String; } class Num(v: int) extends super.Num(v) with Exp { def show = value.toString(); }}
trait BasePlus extends Base { class Plus(l: exp, r: exp) extends Exp { val left = l; val right = r; def eval = left.eval + right.eval }}trait BaseNeg extends Base { class Neg(t: exp) extends Exp { val term = t; def eval = - term.eval; }}trait BasePlusNeg extends BasePlus with BaseNeg;trait ShowPlusNeg extends BasePlusNeg with Show { class Plus(l: exp, r: exp) extends super.Plus(l, r) with Exp { def show = left.show + "+" + right.show; } class Neg(t: exp) extends super.Neg(t) with Exp { def show = "-(" + term.show + ")"; }}
object HelloWorld extends Application { println("Hello, world!")}
Traits – back to HelloWorldTraits – back to HelloWorld
Surprise: Application is a trait!● The main() method of the Application trait provides the ubiquitous entry point for
Java applications
● Since Application is a trait, the method actually "shows up" on the subclass (HelloWorld).
● To execute this method, it is necessary to create the HelloWorld singleton, which means constructing an instance of HelloWorld, which means "playing" the body of the class, which effectively executes the application.
● Only after that is complete does the trait's main() get invoked
Implicit conversions (views)Implicit conversions (views)
Scala allows to define special methods which take a value of a certain type (B) in as a parameter and return a value of a different type (A) as the result. By marking this method implicit, you tell the compiler to automatically use this conversion in situations where a value of type A is called for but a value of type B was passed.implicit def str2int(str:String):Int = Integer.parseInt(str)def addTwo(a:Int, b:Int) = a + b
addTwo("123", 456)
Implicit conversions -Implicit conversions -usage exampleusage example
for (i <- 0 until args.length) ...
implicit def intWrapper(x:Int):RichInt = new RichInt(x)
Adding methods to classes. Back to the loop we saw:
val range = 0.until(args.length)for (i <- range) ...
=
Where does method until come from? scala.runtime.RichIntHow does 0:Int become a RichInt? scala.Predef has
Advanced classes and Advanced classes and methodsmethods
Packages and importsRicher import syntax, import anywhere in the code
Implicit parametersIf implicit object of matching type is found “in scope” it can
replace a missing parameterInner classes and nested functions
inner classes are per instance, unlike in JavaOperators
any method can be used as infix operatorCurrying
when a method is called with a fewer number of parameters, this will yield a function taking the missing parameters as its arguments.
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
GenericsGenerics
abstract class TreeSet[A] { def incl(x: A): TreeSet[A]; def contains(x: A): boolean;}
trait TreeSet[A <: Ordered[A]] { def incl(x: A): TreeSet[A]; def contains(x: A): boolean;}
The contains and incl methods compare elements using methods < and >. For an arbitrary type parameter we cannot guarantee it has these two methods.
A view bounded type parameter clause [a <% T] only specifies that the bounded type a must be convertible to the bound type T, using an implicit conversion
trait TreeSet[A <% Ordered[A]] { ...}
Scala Generics are erased after compilation, just like in Java.
We can enforce the comparability of a type by demanding that it is a subtype of Ordered trait.
class TreeSet<T extends Comparable<? super T>>In Java we need to do something like:
Generics - VarianceGenerics - Variance
class Stack[+a] { def push(x: a): Stack[a] = ^ covariant type parameter a appears in contravariant position.
A covariant type parameter of a class may only appear in covariant positions: values in the class, result types of methods in the class, and type arguments to other covariant types, but not types of formal method parameters.
Using lower bounds, we can generalize the push method in Stackclass Stack[+a] { def push[b >: a](x: b): Stack[b] = new NonEmptyStack(x, this)
Besides +, there is also a - prefix which indicates contra-variant subtyping.
Some Scala library collections are covariant (unlike Java)
object EmptyStack extends Stack[Nothing] { ... }
Covariant sub-typing class Stack[+a] { ...}
Advanced GenericsAdvanced Generics● Type variables● Self types
● Existential types (Java generics interoperability, wildcards)
Example: def m(x : T forSome {type T <: A}) = x is a method that takes arguments that conform to T <: A, it can be written also as def m(x: _ <: A) = x = Java's ? extends A
● Kinds - Generics of a Higher Kind (in progress)
abstract class Graph { type Edge type Node <: NodeIntf abstract class NodeIntf { def connectWith(node: Node): Edge } def nodes: List[Node] def edges: List[Edge] def addNode: Node}
T forSome {type Q}
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
Cool stuff: Cool stuff: Option and Either MonadsOption and Either Monads
● Often a method needs to return either a value or nothing, depending on various conditions (Haskell's Maybe)
● Option[A] is a sealed case class in the Scala core libraries with 2 subclasses: Some(a:A) and None
● Either is another sealed case Either[A,B] with Left(a:A) and Right(b:B) options
Cool stuff: Cool stuff: Structural typesStructural types
● Structural typing offers the ability to reduce the scope of polymorphism only over the subset of behaviors that need to be common between the classes.
● Scala offers the benefit of both dynamic and statically typed worlds through its implementation of structural typing - a compile time checked duck typing.
Cool stuff:Cool stuff:Extractor objectsExtractor objects
Paper: Matching Objects with Patterns
In Scala, patterns can be defined independently of case classes. To this end, a method named unapply is defined to yield a so-called extractor.
Extractor object:object Twice { def apply(x: Int): Int = x * 2 def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None}
object TwiceTest extends Application { val x = Twice(21) x match { case Twice(n) => println(n) } // prints 21}
Cool stuff - Cool stuff - Concurrency & ActorsConcurrency & Actors
● Moore's law has changed, we don’t get the same increase in clock frequency as we used to, instead, we get more cores.
● Solve the problem by (re)writing software to be concurrent.● Actors (programming model borrowed from Erlang) implemented as a Scala
library implements Message-Passing Concurrency rather than Shared-State Concurrency (the scheme adopted by C, Java, C# etc.) Actors have no shared state and are communicating by sending and receiving messages which makes it possible to write code that is deterministic and side-effect-free.
● Unlike Erlang VM (BEAM) where process is very lightweight, Scala actor is either thread-based or event based. Former is limited in number, latter can block its OS thread.
● Erlang is a functional language - data is immutable, in Scala programmer needs to take care of that alone.
● Scala is statically typed, while Erlang is dynamic● Erlang uses tail recursion all the time, while Scala uses traditional iterations
(tail recursion in JVM is problematic)● Erlang has built-in code hot-swapping capabilities, the possibilities for hot-
swapping in Scala are limited because of static typingfrom Jonas Boner and Yariv Sadan
Paper: Event-Based Programming without Inversion of Control
More cool stuffMore cool stuff
● XML processing – native XML● Monads● Partial functions (isDefinedAt)● Lazy values (lazy)● Annotations (@)● Parser combinators library● ...
In this presentation:In this presentation:
● Motivation and History● Meet Scala● Simple data structures and loops● Objects● Types and Generics● Advanced topics● Conclusions and references
Scala compared to JavaScala compared to Java
The power of ScalaThe power of Scala
Scala supports several programming paradigms off the shelf...
operator = method = function = objectoperator = method = function = object
Functional programming:Makes it easy to build interesting things from simple parts, using - higher-order functions, - algebraic types and pattern matching, - parametric polymorphism.
Object-oriented programming:Makes it easy to adapt and extendcomplex systems, using - subtyping and inheritance, - dynamic configurations, - classes as partial abstractions.
““Scalable language”Scalable language”
Programmer can define language constructs
def While (p: => Boolean) (s: => Unit) { if (p) { s ; While(p)(s) }}
...and allows the programmer to extend it with completely new paradigms.
Nobody's perfect... Nobody's perfect... ● Language specification constantly changing● Lack of proper reflection support
(undocumented)● Not enough/inadequate documentation for
beginners● Lacking proper IDE support● Too many ways to do one thing, multi-
paradigm language problem (as in C++, Perl) - can Scala really scale on LoC?
And the industry goes...And the industry goes...
http://stuffthathappens.com
ReferencesReferences● Scala for Java refugees (Daniel Spiewak)● The busy Java developer's guide to Scala (Ted Neward)● Ricky Clarkson, David R. MacIver, Henrik Huttunen, Debasish Ghosh● A tour of Scala and other resources on http://www.scala-lang.org/● http://scala-blogs.org/● Scala forums @ Nabble● Scalazine @ Artima● Programming in Scala (book) (M. Odersky, L. Spoon, B. Venners)● Martin Odersky's Weblog● The Scala Experiment (video) , JavaOne 2008 Scala (audio and slides)● Scala APIs
Thank you!Thank you!
top related