Title: Multiparadigm Programming in Scala
1Multiparadigm Programming in Scala
- Adapted from presentation by
- H. C. Cunningham and J. C. Church University of
Mississipi
2What is Multiparadigm Programming?
- Definition
- A multiparadigm programming language provides a
framework in which programmers can work in a
variety of styles, freely intermixing constructs
from different paradigms. Tim Budd - Programming paradigms
- imperative versus declarative (e.g., functional,
logic) - other dimensions object-oriented,
component-oriented, concurrency-oriented, etc.
3Why Learn Multiparadigm Programming?
- Tim Budd
- Research results from the psychology of
programming indicate that expertise in
programming is far more strongly related to the
number of different programming styles understood
by an individual than it is the number of years
of experience in programming. - The goal of multiparadigm computing is to
provide ... a number of different problem-solving
styles so that a programmer can select a
solution technique that best matches the
characteristics of the problem.
4Why Teach Multiparadigm Programming?
- Contemporary imperative and object-oriented
languages increasingly have functional
programming features, e.g., - higher order functions (closures)
- list comprehensions
- New explicitly multiparadigm (object-oriented/func
tional) languages are appearing, e.g., - Scala on the Java platform (and .Net in future)
- F on the .Net platform
5Scala
- Programming language developed by Martin
Oderskys team at EPFL in Switzerland - Executes on the Java platform
- Integrates with Java
- Has growing usage (e.g., Twitter, Foursquare, and
Linkedin) - Multiparadigm language
- Object-oriented (with generics and mixins)
- Functional (similar to Haskell and SML)
- Extensible (method calls as operators, currying,
closures, by-name parameters) - Actor-based concurrency-oriented programming
- Language-oriented programming
- Statically typed with Hindley-Milner type
inference
6Why Scala? (Coming from Java/C)
- Runs on the JVM
- Can use any Java code in Scala
- Almost as fast as Java (within 10)
- Much shorter code
- Odersky reports 50 reduction in most code over
Java - Local type inference
- Fewer errors
- No Null Pointer problems
- More flexibility
- As many public classes per source file as you
want - Operator overloading
7Scala References
- Website http//www.scala-lang.org
- Martin Odersky. Scala Tutorial for Java
Programmers. - Martin Odersky. Scala By Example.
- Martin Odersky, Lex Spoon, and Bill Venners.
Programming in Scala A Comprehensive
Step-By-Step Guide, 2nd Edition, Artima, Inc.,
2010. - Books on Scala
- http//www.scala-lang.org/node/959
8Scala object system
- Class-based
- Single inheritance
- Can define singleton objects easily (no need for
static which is not really OO) - Traits, compound types, and views allow for more
flexibility
9Basic Scala
- Use var to declare variables
- var x 3
- x 4
- Use val to declare values (final vars)
- val y 3
- y 4 // error
- Notice no types, but it is statically typed
- var x 3
- x hello world // error
- Type annotations
- var x Int 3
-
10Functional Scala
- Defining lambdas nameless functions
- val f x Int gt x 42 f mapping int -gt
int - Closures! A way to haul around state
- var y 3
- val g x Int gt y 1 xy
- Maps (and a cool way to do some functions)
- List(1,2,3).map(_10).foreach(println)
- Filtering (and ranges!)
- 1 to 100 filter (_ 7 3) foreach (println)
- (Feels a bit like UNIX pipes?)
11Defining Hello World
- object HelloWorld
- def main(args ArrayString)
- println("Hey world!")
-
-
- Singleton object named HelloWorld (also replaces
static methods and variables) - Method main defined (procedure)
- Parameter args of type ArrayString
- Array is generic class with type parameter
12Interpreting Hello World
- gt scala
- This is a Scala shell.
- Type in expressions to have them evaluated.
- Type help for more information.
- scalagt object HelloWorld
- def main(args ArrayString)
- println("Hey world!")
-
-
- defined module HelloWorld
- scalagt HelloWorld.main(null)
- Hey world!
- unnamed0 Unit ()
- scalagtq
13Compiling Executing Hello World
- gt scalac HelloWorld.scala
- gt scala HelloWorld
- Hey world!
14Numbers are Objects
- Consider expression
- 1 2 3 / x
- Operators are method calls (like Smalltalk)
- Operator symbols are identifiers
- Expression above is same as
- (1).(((2).(3))./(x))
15Functions are Objects
- object Timer
- def oncePerSecond(callback() gt Unit)
- while (true)
- callback() Thread sleep 1000
- // 1-arg method sleep used as operator
-
- def welcome()
- println("Welcome to CS3180!")
-
- def main(args ArrayString)
- oncePerSecond(welcome)
-
16Timer Execution
- scalagt l Timer.scala
- Loading Timer.scala...
- defined module Timer
- scalagt Timer.main(null)
- Welcome to CS3180!
- Welcome to CS3180!
- Welcome to CS3180!
-
17Anonymous Functions
- object Timer
- def oncePerSecond(callback() gt Unit)
- while (true)
- callback() Thread sleep 1000
-
-
- def main(args ArrayString)
- oncePerSecond(
- () gt println("Welcome to CS3180!") )
-
18Classes
- class Complex(real Double, imag Double)
- def re real
- def im imag
-
- Class primary constructor combined with class
body - Parameters of class private constants within
class - Parameterless methods re and im
- Return types of re and im inferred from
expression (cannot be inferred for recursive
functions) - Thus more concise syntax
19Method Overriding
- // Complex.scala
- class Complex(real Double, imag Double)
- def re real
- def im imag
- override def toString
- re (if (im lt 0.0) "" else "")
- im I"
-
- Classes extend class AnyRef by default
- Methods must explicitly override parent method
- if expressions
20Using Classes and Objects
- scalagt load Complex.scala
- Loading Complex.scala...
- defined class Complex
- scalagt val x new Complex(1,-3)
- x Complex 1.0-3.0i
- scalagt x.toString
- res0 java.lang.String 1.0-3.0i
21Case Classes
- abstract class Tree // Expression Trees
- case class Sum(l Tree, r Tree)
- extends Tree
- case class Var(n String) extends Tree
- case class Const(v int) extends Tree
- Cf. Algebraic data types as in functional
languages - Keyword new not needed to create instances
(objects) - Getters defined automatically for constructor
parameters - Pattern matching can be used to decompose
- equals method defined on structure of instances
22Pattern Matching
- object Expressions
- type Environ String gt Int
- def eval(t Tree, env Environ) Int t match
- case Sum(l,r) gt eval(l,env) eval(r,env)
- case Var(n) gt env(n)
- case Const(v) gt v
-
- def derive(t Tree, v String) Tree t match
- case Sum(l,r) gt Sum(derive(l,v),
- derive(r,v))
- case Var(n) if (v n) gt Const(1)
- case _ gt Const(0)
-
23Test Expression Trees
- def main(args ArrayString)
- val exp Tree
- Sum(Sum(Var("x"),Var("x")),
- Sum(Const(7),Var("y")))
- val env Environ
- case "x" gt 5 case "y" gt 7
- println("Expression " exp)
- println("Evaluation with x5, y7 "
- eval(exp,env))
- println("Derivative relative to x\n "
- derive(exp, "x"))
- println("Derivative relative to y\n "
- derive(exp, "y"))
-
24Execute Expression Trees
- scalagt load Expressions.scala
- Loading Expressions.scala...
-
- scalagt Expressions.main(null)
- Expression Sum(Sum(Var(x),Var(x)),Sum(Const(7),Va
r(y))) - Evaluation with x5, y7 24
- Derivative relative to x
- Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0)
)) - Derivative relative to y
- Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)
)) -
25Defs, Vals, and Vars
- Three types of identifier definitions
- def defines functions with parameters RHS
expression evaluated each time called - val defines unchanging values RHS expression
evaluated immediately to initialize - var defines storage location whose values can be
changed by assignment statements RHS expression
evaluated immediately to initialize
26Traits
- trait Ord // Order comparison operators
- def lt (that Any) Boolean // abstract
- def lt(that Any) Boolean
- (this lt that) (this that)
- def gt (that Any) Boolean
- !(this lt that)
- def gt(that Any) Boolean
- !(this lt that)
-
- Like Java interfaces except can have concrete
methods - Can be mixed-in to class
- Note that lt is abstract others defined with lt
and equals -
27Date Class with Mixin Trait Ord
- class Date(y Int, m Int, d Int)
- extends Ord
- def year y
- def month m
- def day d
- override def toString() String
- year "-" month "-" day
- // need definition of lt and equals
-
- Can only extend one class or trait
- May mix-in additional classes using keyword with
28Date Class Equals Method
- override def equals(that Any) Boolean
- that.isInstanceOfDate
- val o that.asInstanceOfDate
- o.day day o.month month
- o.year year
-
- isInstanceOfT checks whether object is an
instance of the given type T - asInstanceOfT casts static type to T if
compatible with dynamic type of object - Value of last statement of function is returned
29Date Class lt Method
- def lt(that Any) Boolean
- if (!that.isInstanceOfDate)
- error("Cannot compare " that
- " and a Date")
- val o that.asInstanceOfDate
- (year lt o.year)
- (year o.year
- (month lt o.month
- (month o.month day lt o.day)))
-
30DateTest
- object DateTest
- def main(args ArrayString)
- val x new Date(1,1,2000)
- val y new Date(12,31,2001)
- println("x " x)
- println("y " y)
- println("x lt y " (xlty))
- println("x gt y " (xgty))
-
31DateTest Output
- gt scala DateTest
- x 1-1-2000
- y 12-31-2001
- x lt y true
- x gt y false
32Scala Functions
- Are first-class values i.e., functions are
objects - Can be higher-order take functions as arguments
or return them as result - Can be anonymous
- May be curried take arguments one at a time,
allowing partial application - Are often passed in a closure with references
to free variables they maninpulate - Provide ability to build powerful libraries of
higher-order functions
33Curried Functions
- scalagt def add(x Int, y Int) x y
- add (Int,Int)Int
- scalagt add(1,3)
- res0 Int 4
- scalagt def addc(x Int)(y Int) x y
- addc (Int)(Int)Int
- scalagt addc(1)(3)
- res1 Int 4
34Partial Application
- scalagt def addc(x Int)(y Int) x y
- addc (Int)(Int)Int
- scalagt val z addc(1) _
- z (Int) gt Int ltfunctiongt
- scalagt z(3)
- res2 Int 4
35Closures
- scalagt val inc 10
- inc Int 10
- scalagt def incre(x Int) x inc
- incre (Int)Int
- scalagt def app(y Int, g (IntgtInt)) g(y)
- app (Int,(Int) gt Int)Int
- scalagt app(13,incre)
- res0 Int 23
36List Processing
- // Not actual Scala API code
- abstract class ListA
- def mapB(f (A)gt B) ListB
- this match
- case Nil gt this
- case xxs gt f(x)xs.map(f)
-
-
- case object Nil extends ListNothing
- case final class B
- (private hd B, val tl ListB)
- extends ListB
37Using List Map
- scalagt val xs List(3,4,5)
- xs ListInt List(3, 4, 5)
- scalagt val triples xs.map(x gt 3x)
- triples ListInt List(9, 12, 15)
- scalagt val evens xs.filter(x gt x20)
- evens ListInt List(4)
38More List Processing
- // Not actual Scala API code
- abstract class ListA
- def filter(p (A) gt Boolean) ListA
- this match
- case Nil gt this
- case xxs gt
- if (p(x)) xxs.filter(p)
- else xs.filter(p)
-
-
39Other Higher Order List Methods
- flatMap
- foldLeft, foldRight
- reduceLeft, reduceRight
- takeWhile, dropWhile
- span, break
- foreach
40For Comprehensions
- scalagt for(i lt- 1 to 30
- j lt- List(2,3,5,7)
- if i j 0) yield (i,j)
- res0 scala.collection.immutable.IndexedSeq(Int,
Int) Vector((2,2), (3,3), (4,2), (5,5),
(6,2), - (6,3), (7,7), (8,2), (9,3), (10,2), (10,5),
(12,2), (12,3), (14,2), (14,7), (15,3), (15,5),
(16,2),(18,2), (18,3), (20,2), (20,5), (21,3),
(21,7), (22,2), (24,2), (24,3), (25,5), (26,2),
(27,3), (28,2), (28,7), (30,2), (30,3), (30,5))
41Example Defining New Control Structure
- object TargetTest with Application
- def loopWhile(def cond Boolean)(def body
Unit) Unit - if (cond)
- body
- loopWhile(cond)(body)
-
- var i 10
- loopWhile (i gt 0)
- Console.println(i)
- i i 1
// Note var/val -
Define loopWhile method
Use it with nice syntax
42Scala class hierarchy
43Actors in Scala
44Motivation
- Concurrency is hard!
- Real World is parallel and distributed.
- Erlang's notion of a process
- Concurrent processes should pass messages to
other processes rather than share memory. - Erlang's processes are part of the language.
- Scala's actors are part of the library.
45Actors
- Actors act independent of other actors.
- Actors have mailboxes.
- Actors communicate by sending messages to other
actors. - Actors will check their mailbox and react to
their messages.
46Message in a Bottle
- Any object can be sent to an Actor
case object myMessageObject ... myActor !
myMessageObject
47Please Mr. Postman
- How urgent is it?
- react I need it now!
- receiveWithin I need it soon!
- receive I'll wait.
- All three methods will perform pattern matching
on the objects received.
48Overacting
- import scala.actors._
- object SillyActor extends Actor
- def act() // Defines how our actor acts
- for (i lt- 1 to 5)
- println(I'm acting!)
- Thread.sleep(1000)
-
-
-
- ...
- SillyActor.start() // Begins acting
49Vegetable Launcher
- case object Tomato
- case object Lettuce
- object VegetableLauncher extends Actor
- def act()
- for (i lt- 1 to 5)
- VegetableCatcher ! Tomato // Send
it! - Thread.sleep(1000)
- VegetableCatcher ! Lettuce // Send
it! - Thread.sleep(1000)
-
-
50Vegetable Catcher
- object VegetableCatcher extends Actor
- def act()
- loop
- react // Non-blocking call
- // Pattern Matching
- case Lettuce gt
- println("I caught a
lettuce!") - case Tomato gt
- println("I caught a tomato!")
-
-
-
51Lights, Camera, ...
- VegetableLauncher.start()
- VegetableCatcher.start()
- SillyActor.start()
I'm acting! I caught a tomato! I'm acting! I
caught a lettuce! I'm acting! I caught a
tomato! I'm acting! I caught a lettuce! I'm
acting! I caught a tomato! I caught a lettuce! I
caught a tomato! I caught a lettuce! I caught a
tomato! I caught a lettuce!
52Dining Philosophers
- Five philosophers compete for limited resources.
- Deadlocks are possible.
- Solution implemented with a waiter.
- 11 actors total
- 5 philosophers
- 5 chopsticks (A mutex actor)?
- 1 waiter (A singleton object actor)?
53- The waiter only allows four to sit. After that,
names are on the wait list. - Philosophers must still wait for chopsticks after
sitting.
54Six Messages
- import scala.actors._
- import scala.actors.Actor._
- import java.util.Random
- // Philosopher and Waiter communication
- case object NeedToEat
- case object HaveASeat
- case object DoneEating
- // Philosopher and Chopstick communication
- case object NeedChopstick
- case object HeresAChopstick
- case object GiveBackChopstick
55Chopstick Mutex
- class Chopstick extends Actor
- def act()
- loop
- react
- case NeedChopstick gt
- sender ! HeresAChopstick
- receive
- case GiveBackChopstick gt
- 1
-
-
-
-