Title: Multiparadigm Programming in Scala
1Multiparadigm Programming in Scala
- H. Conrad Cunningham
- James C. Church
- Computer and Information Science
- University of Mississippi
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,
language-oriented
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
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 to be solved.
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.com)
- 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
6Scala 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, Artima, Inc., 2009. - Books from Apress and Pragmatic Bookshelf in May,
OReilly in August, Cambridge late 2009
7Defining Hello World
- object HelloWorld // Mississippi version
- 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
8Interpreting 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
9Compiling Executing Hello World
- gt scalac HelloWorld.scala
- gt scala HelloWorld
- Hey world!
10Numbers 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))
11Functions 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 CCSCMS!")
-
- def main(args ArrayString)
- oncePerSecond(welcome)
-
12Timer Execution
- scalagt l Timer.scala
- Loading Timer.scala...
- defined module Timer
- scalagt Timer.main(null)
- Welcome to CCSCMS!
- Welcome to CCSCMS!
- Welcome to CCSCMS!
-
13Anonymous Functions
- object Timer
- def oncePerSecond(callback() gt Unit)
- while (true)
- callback() Thread sleep 1000
-
-
- def main(args ArrayString)
- oncePerSecond(
- () gt println("Welcome to CCSCMS!") )
-
14Classes
- 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
15Method 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
16Using 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
17Case 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
- Algebraic data types as in functional languages
- Keyword new not needed to create instances
(objects) - Getters defined automatically for constructor
parameters - equals method defined on structure of instances
- Pattern matching can be used to decompose
18Pattern 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)
-
19Test 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"))
-
20Execute 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)
)) -
21Defs, 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
22Traits
- 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 lt abstract others defined with lt and equals
-
23Date 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 only one class or trait
- May mix-in additional classes using keyword with
24Date 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
25Date 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)))
-
26DateTest
- 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))
-
27DateTest Output
- gt scala DateTest
- x 1-1-2000
- y 12-31-2001
- x lt y true
- x gt y false
28Scala 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
29Curried 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
30Partial 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
31Closures
- 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
32List 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
33Using 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)
34More 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)
-
-
35Using List Filter
- scalagt val xs List(3,4,5,6)
- xs ListInt List(3, 4, 5, 6)
- scalagt val evens xs.filter(x gt x20)
- evens ListInt List(4, 6)
36Other Higher Order List Methods
- flatMap
- foldLeft, foldRight
- reduceLeft, reduceRight
- takeWhile, dropWhile
- span, break
- foreach
37For Comprehensions
- scalagt for(i lt- 1 to 30
- j lt- List(2,3,5,7)
- if i j 0) yield (i,j)
- res0 Seq.Projection(Int, Int) RangeG((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))
38Actors in Scala
39Motivation
- 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.
40Actors
- 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.
41Message in a Bottle
- Any object can be sent to an Actor
case object myMessageObject ... myActor !
myMessageObject
42Please 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.
43Overacting
- 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
44Vegetable 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)?
-
-
45Vegetable 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!)? -
-
-
46Lights, Camera, ...
- VegtableLauncher.start()?
- VegtableCatcher.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!
47Dining 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)?
48- The waiter only allows four to sit. After that,
names are on the wait list. - Philosophers must still wait for chopsticks after
sitting.
49Six 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
50Chopstick Mutex
- class Chopstick extends Actor
- def act()
- loop
- react
- case NeedChopstick gt
- sender ! HeresAChopstick
- receive
- case GiveBackChopstick gt
- 1
-
-
-
-