Scala at HUJI PL Seminar 2008
Upcoming SlideShare
Loading in...5

Scala at HUJI PL Seminar 2008






Total Views
Views on SlideShare
Embed Views



0 Embeds 0

No embeds


Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
Post Comment
Edit your comment

Scala at HUJI PL Seminar 2008 Scala at HUJI PL Seminar 2008 Presentation Transcript

  • Introduction to Scala programming language Yardena Meymann June 2008
  • 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: ● Motivation and History ● Meet Scala ● Simple data structures and loops ● Objects ● Types and Generics ● Advanced topics ● Conclusions and references
  • Java Architecture javac HelloWorld.class load class Java Virtual Machine Java Class Garbage Libraries Loader Collector Bytecode Executor JIT HotSpot compiler interpret execute Native OS
  • Java as a Platform HelloWorld.**** ****c HelloWorld.class load class Java Virtual Machine Java Class Garbage Libraries Loader Collector ...
  • JVM Languages ● Scala ● JRuby ● Groovy ● Jython ● BeanShell ● Rhino Javascript ● JavaFX Script ● Kawa Scheme ● ... ● Clojure Lisp ● hundreds of others...
  • 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? ● 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
  • Java and Scala History Java Java 1.1 announced, 1997 first beta Java Java 1.5 Java 1.6 J. Gosling release 1.0 Java 1.2 Java 1.3 Java 1.4 (Tiger) (Mustang) 1991 1995 1996 1998 2000 2002 2004 2006 GJ 1999 work on Scala M. Odersky starts 1995 1999 2001 1.0 2003 2.0 2006
  • In this presentation: ● Motivation and History ● Meet Scala ● Simple data structures and loops ● Objects ● Types and Generics ● Advanced topics ● Conclusions and references
  • Hello Scala object HelloWorld extends Application { ● object = singleton class ● optional semicolon println("Hello, world!") ● def } ● implicit public ● type after name, optional object HelloWorld { ● generics using [ ] def main(args: Array[String]) = Unit = : ● unit = void System.out.println("Hello, world!") ● calling into java.lang library } ● different constructor syntax
  • Simple Greeting def main(args:Array[String]) = { immutable variable val size = args.length type int inferred println("Greeting " + size + " members:") mutable variable var greeting = "Hello " type String int is an object, inferred alternative method for (i <- 0 until args.length) { invocation syntax greeting += (args(i) + ",") Java-like loop } array element access if (args.length > 0) greeting = greeting.substring(0, greeting.length – 1) greeting += "!" if statement println(greeting); }
  • Simple Timer object SimpleTimer { function type def oncePerSecond(callback: () => unit) { while (true) { callback(); Thread.sleep(1000) } } def timeFlies() { println("time flies like an arrow...") } def main(args: Array[String]) { functions are objects oncePerSecond(timeFlies) } }
  • Reusable 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 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) + ",") args.foreach(arg => greeting += (arg + " ")) } if (args.length > 0) greeting = greeting.substring(0, greeting.length – 1) greeting += "!" println(greeting); }
  • In this presentation: ● Motivation and History ● Meet Scala ● Simple data structures and loops ● Objects ● Types and Generics ● Advanced topics ● Conclusions and references
  • Tuples 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]
  • Map val treasureMap = new HashMap[Int, String] treasureMap += 1 -> "Go to island." treasureMap += 2 -> "Find big X on ground." treasureMap += 3 -> "Dig." println(treasureMap(2)) 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. val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V") println(romanNumeral(4))
  • Comprehensions val filesHere = (new".")).listFiles for ( file <- filesHere; if file.isFile; Types with no typing! if file.getName.endsWith(".scala") ) println("Found " + file) 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
  • Comprehensions defined Example: for (val p ← persons; p.age > 20) yield Generally, a for-comprehension is of the form for ( s ) yield e s 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
  • Comprehensions make programs short and clear Java QuickSort Scala QuickSort
  • Basic 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: ● Motivation and History ● Meet Scala ● Simple data structures and loops ● Objects ● Types and Generics ● Advanced topics ● Conclusions and references
  • Everything 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 hierarchy
  • Null 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 basics ● Properties ● Constructors ● Constructor properties ● Abstract methods ● Override methods
  • Simple property and default constructor Java: Scala: public class Person { (var name: String) class Person { private String name = null; var name: String public Person(String name) { } = name; } ... public String getName() { println( return name; } public void setName(String name) { = name; } }
  • Constructors, operators, overriding methods class Rational(n:Int, d:Int) { Default constructor private def gcd(x:Int, y:Int): Int = { ...//greatest common denominator } Object initialization uses private val g = gcd(n,d) constructor properties, read-only properties defined val numer:Int = n/g val denom:Int = d/g Alternative constructor; def this(n:Int) = { this(n, 1) } must call the default constructor def +(that:Rational) = new Rational(numer*that.denom + that.numer*denom, denom * that.denom) def -(that:Rational) = ... Operators def *(that:Rational) = ... defined def /(that:Rational) = ... override def toString() = "Rational: [" + numer + " / " + denom + "]" } Override method – override modifier is mandatory
  • Abstract class abstract class Shape { var fillColor:Color = null Property def draw(g:Graphics):Unit Abstract methods def area:Double }
  • Subclasses class Circle(var radius:Int) extends Shape { class Square(var width:Int) extends Shape { def draw(g:Graphics):Unit = { def draw(g:Graphics):Unit = { if (fillColor == null) { if (fillColor == null) { g.drawOval(0, 0, radius / 2, radius / 2) g.drawRect(0, 0, width, width) } else { } else { g.setColor(fillColor); g.setColor(fillColor) g.fillOval(0, 0, radius / 2, radius / 2) g.fillRect(0, 0, width, width) } } } } def area:Double = { def area:Double = width * width var back = Math.Pi * radius } back * radius } }
  • Advanced 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 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 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 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 pseudo-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 Object Function object has one or more apply methods: object Square { def apply(in: double) = in * in def apply(in: float) = in * in def apply(in: int) = in * in } val xSquared = Square(x) Doug Pardee Together with companion object feature, it is used to facilitate the Factory Method design pattern, as we saw in previous Map example: val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
  • ADTs 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 - Example The output will look something like this: Red: 100 Blue: 220 R: 100, G: 200, B: 50 Invalid color
  • Another Case Class Set of definitions for binary tree: In-order traversal of binary tree:
  • Case 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 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 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 Mixin 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 - Example
  • Traits – 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 Seeing trait Reading extends Person { self: Seeing => ... } ● In contrast to classes, traits may not have constructor parameters.
  • Mixins He who defs last, defs best The order in which traits are mixed-in determines overriding strategy “Expression problem” example: trait Base { trait BasePlus extends Base { type exp <: Exp; class Plus(l: exp, r: exp) extends Exp { trait Exp { val left = l; val right = r; def eval: int def eval = left.eval + right.eval } } class Num(v: int) extends Exp { } val value = v; trait BaseNeg extends Base { def eval = value class Neg(t: exp) extends Exp { } val term = t; } def eval = - term.eval; } } trait Show extends Base { trait BasePlusNeg extends BasePlus with BaseNeg; type exp <: Exp; trait Exp extends super.Exp { trait ShowPlusNeg extends BasePlusNeg with Show { def show: String; class Plus(l: exp, r: exp) extends } super.Plus(l, r) with Exp { class Num(v: int) extends def show = + "+" +; super.Num(v) with Exp { } def show = value.toString(); class Neg(t: exp) extends super.Neg(t) with Exp { } def show = "-(" + + ")"; } } }
  • Traits – back to HelloWorld object HelloWorld extends Application { println("Hello, world!") } 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) 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 - usage example Adding methods to classes. Back to the loop we saw: for (i <- 0 until args.length) ... = val range = 0.until(args.length) for (i <- range) ... Where does method until come from? scala.runtime.RichInt How does 0:Int become a RichInt? scala.Predef has implicit def intWrapper(x:Int):RichInt = new RichInt(x)
  • Advanced classes and methods Packages and imports Richer import syntax, import anywhere in the code Implicit parameters If implicit object of matching type is found “in scope” it can replace a missing parameter Inner classes and nested functions inner classes are per instance, unlike in Java Operators any method can be used as infix operator Currying 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: ● Motivation and History ● Meet Scala ● Simple data structures and loops ● Objects ● Types and Generics ● Advanced topics ● Conclusions and references
  • Generics Scala Generics are erased after compilation, just like in Java. abstract class TreeSet[A] { The contains and incl methods def incl(x: A): TreeSet[A]; compare elements using methods < and >. def contains(x: A): boolean; For an arbitrary type parameter we cannot } guarantee it has these two methods. We can enforce the comparability of a trait TreeSet[A <: Ordered[A]] { type by demanding that it is a subtype def incl(x: A): TreeSet[A]; of Ordered trait. def contains(x: A): boolean; } In Java we need to do something like: class TreeSet<T extends Comparable<? super T>> A view bounded type parameter trait TreeSet[A <% Ordered[A]] { clause [a <% T] only specifies that ... the bounded type a must be } convertible to the bound type T, using an implicit conversion
  • Generics - Variance Some Scala library collections are covariant (unlike Java) Covariant sub-typing class Stack[+a] { 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. class Stack[+a] { def push(x: a): Stack[a] = ^ covariant type parameter a appears in contravariant position. Using lower bounds, we can generalize the push method in Stack class 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. object EmptyStack extends Stack[Nothing] { ... }
  • Advanced Generics ● Type variables abstract class Graph { type Edge type Node <: NodeIntf ● Self types abstract class NodeIntf { def connectWith(node: Node): Edge } def nodes: List[Node] def edges: List[Edge] def addNode: Node } ● Existential types (Java generics interoperability, wildcards) T forSome {type Q} 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)
  • In this presentation: ● Motivation and History ● Meet Scala ● Simple data structures and loops ● Objects ● Types and Generics ● Advanced topics ● Conclusions and references
  • Cool stuff: Option 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: Structural 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: Extractor 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 - Concurrency & Actors Paper: Event-Based Programming without Inversion of Control ● 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 typing from Jonas Boner and Yariv Sadan
  • More cool stuff ● XML processing – native XML ● Monads ● Partial functions (isDefinedAt) ● Lazy values (lazy) ● Annotations (@) ● Parser combinators library ● ...
  • 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 Java
  • The power of Scala operator = method = function = object Scala supports several programming paradigms off the shelf... Functional programming: Object-oriented programming: Makes it easy to build Makes it easy to adapt and interesting things from extend simple parts, using complex systems, using - higher-order functions, - subtyping and inheritance, - algebraic types and - dynamic configurations, pattern matching, - classes as partial abstractions. - parametric polymorphism.
  • “Scalable language” ...and allows the programmer to extend it with completely new paradigms. Programmer can define language constructs def While (p: => Boolean) (s: => Unit) { if (p) { s ; While(p)(s) } }
  • 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...
  • References ● 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 ● ● 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!