scala at huji pl seminar 2008

Post on 06-May-2015

1.530 Views

Category:

Education

1 Downloads

Preview:

Click to see full reader

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