28
Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015 © 1

Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Embed Size (px)

Citation preview

Page 1: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

ScalaTechnion – Institute of Technology

Software Design (236700)

Based on slides by: Sagie Davidovich, Assaf Israel

Author: Gal Lalouche - Technion 2015 ©

1

Page 2: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

What is Scala?

Scala is a static object-functional language

It supports fully object-oriented code

Classes, methods, inheritance, visibility modifiers,…

It is actually more object-oriented than Java, due to lack of primitives, no static members

It supports fully functional code

Lambdas, Closure, Currying, pattern matching, lazy evaluation, tail recursion,…

Most importantly, it allows the developer to mix and match the two

Currying on methods, inheriting functions, …

Compiles to Java bytecode

So it’s easy to call Java from Scala and vice-versa

Author: Gal Lalouche - Technion 2015 ©

2

Page 3: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

A note on the “new” features in Java 8All the new features in Java 8 have been in Scala for years

Higher order functions

optional values

Lambda Expressions

The syntactic sugar of Functional Interfaces can be implemented using implicit

default methods on interfaces are actually weak traits

Streams and easy parallelization

Author: Gal Lalouche - Technion 2015 ©

3

Page 4: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Java:

Scala:

Java vs Scala code

Author: Gal Lalouche - Technion 2015 ©

4

class Person {private final String name;private final int age;public Person(String name, int age) {

this.name = name;this.age = age;

}public String getName() { return name; }public int getAge() { return age; }public boolean canDrink() { return age >= 21; }

public String getFirstName() { return name.split(" ")[0]; }}

class Person (val name: String, val age: Int) { def canDrink = age >= 21 val getFirstName: String = name split " " apply 0}

Page 5: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Java:

Scala:

Case classes

Author: Gal Lalouche - Technion 2015 ©

5

case class Person(id: Long) // includes getters/hash/equals/toString

public class Person { long id; @Override public String toString() { return "Person [id=" + id + "]"; } @Override public int hashCode() { return result = 31 + (id ^ (id >>> 32)); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; return id != other.id; }}

Page 6: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Java vs. Scala, at a glance

Java 8 Has primitives

No operator overloading

Statements and expressions

Has static methods and members

Some type inference

Library collections are mutable

default methods

Basic switch functionality

Basic foreach functionality

No extension methods

Has checked exceptions

Type Erasure (JVM property)

Little to no syntactic sugar

Scala Everything is an object

No concept of "operators", just methods

Everything is an expression

Uses a companion object/Singleton

Stronger type inference

Collections are immutable by default

traits

Powerful pattern matching (a la ML)

Powerful for comprehensions

Can define implicit coercions

Doesn’t have checked exceptions

Can get around type erasure

A lot (too much?) of syntactic sugar

6

Page 7: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Everything is an object

Author: Gal Lalouche - Technion 2015 ©

7

Scala has no primitive types

Int is the type of integers and Double is the type of Double Precision

All classes extends Any (this is called a unified type system)

Nothing extends everything (this is called a bottom type)

1 + 2 is actually syntactic sugar for 1.+(2)

Scala allows you to forgoe the . and parenthesis under certain conditions

This also means that operator overloading is supported implicitly

Simply define a method named + or *, or / or pretty much anything…

For example, XML parsing:

val forecast = weather \ "channel" \\ "item" \ "forecast"

Page 8: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Everything is an expression8

In Scala, all statements are actually expressions

Although some may be of type Unit (Scala’s void)

val x: Int = if (flag) 10 else 20 // no need for ?:val compound = { // doSomeCalculation … $ // last argument is considered the return value}val y: Seq[Int] = for (i <- 0 to 10) yield i // list comprehensions

var z = 0val unit: Unit = (z = 10)

val file = try { readFile() } catch { case _: Exception => readOtherFile()}

Page 9: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Object companion

Author: Gal Lalouche - Technion 2015 ©

9

Scala has no static members / methods

Instead, it uses the Singleton pattern and the object keyword

Wait, isn’t Singleton evil?

Well, usually…

But objects are more powerful than simple static methods, since they can also be passed around, extend classes, etc.

Java Scalaclass Person { String name; static boolean isLegal(String name) { //… }}

class Person(val name: String) {}

object Person { def isLegal(name: String) = //…}

Page 10: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Type inference10

Scala has strong type inference (though not as strong as Haskell/ML)

For variables

For methods

For Lambdas

We can also state the explicit return type to have it enforced by the compiler

var x = 3 // discouraged in Scalaval str = "Hello world!" // str’s reference cannot be changed

def getString = {return "Hello world!"

}

List("1","2","3") map (i => i.toInt())

def getString: String = 4 // won’t compileval getInt: Int = "foobar" // won’t compile

Page 11: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Immutability11

So you want to write immutable code in Java…

We can use the final (val in Scala) modifier, but that only applies to the reference itself

What about the referenced object? It can be mutable!

If we want our classes to be truly immutable we have to work hard

We can use immutable objects, but most of the standard java classes and data structures are mutable

This means we have to resort to defensive copying, which is verbose, slow and error-prone

In Scala, all data structures are immutable (“persistent”) by default

This also gives us free generic covariance (i.e., List[Int] extends List[Any])

Page 12: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Traits12

Scala replaces interfaces with traits

Traits are behavioural units, designed for software reuse

Can be composed to create new traits

An alternative to multiple inheritance (e.g., C++) and mixins (e.g., Ruby)

Difference between Traits, Mixins and Multiple Inheritance

Composed traits are flat, mixins are linear and multiple inheritance is a directed acyclic graph

Traits only have a default constructor

Trait conflicts are solved explicitly by the programmer

Page 13: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Traits – Conflict resolution13

Trait conflicts are resolved explicitly

Conflicts can only arise when there are two implementations with the same signature

Since there are no constructors, and all conflicts are resolved explicitly, the model is much simple than multiple inheritance

trait Hodor { def speak = "Hodor!"}trait Stark { def speak = "Winter is coming"}class StarkHodor extends Hodor with Stark { override def speak = "Hodor is coming!" // we can also use super[Hodor].speak }

Page 14: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Traits vs. default Methods14

Traits can be viewed as more powerful default methods

default methods cannot implement non-default methods

Traits can have state

interface Bar { void bar();}interface Foo { default void bar() {…}}class FooBar implements Foo, Bar { // the method bar is considered in conflict and needs to resolved}

trait Counter { var x = 0}

Page 15: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Traits vs. default Methods (cont.)s15

Trait composition can be used to provide required implementationtrait Bar { def bar // this is a required method}trait Foo { def bar = {…} // this is a provide}class FooBar extends Foo with Bar {

// doesn’t need to implement bar}

Page 16: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Traits vs. default Methods (cont.)16

Traits can be composed in runtime (this actually borrows from mixins, i.e., conflicts are resolved linearly)

Traits can access the implementing class instance.

A trait can require more than just methods from its implementing class; it can also impose lower bounds

This is also used for dependency injection (the “cake pattern”)

trait Dancer { def dance = …}class Cat { …}val dancingCat = new Cat with DancerdancingCat.dance

Page 17: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Pattern matching

Author: Gal Lalouche - Technion 2015 ©

17

Scala has a powerful pattern matching mechanism

Simple switch

Type matching

val y = 10val x = y match { case 3 => … case 4 => … case _ => … //default}

val x = y match { case s: String => … case i: Int => … case d: Double => … case tuple: (Int, String) => …} // no match will throw an exception

Page 18: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Pattern matching – sealed classes

Author: Gal Lalouche - Technion 2015 ©

18

Sealed classes can only be extended in the same source file

This generates a compile error for none-exhaustive search

sealed abstract class LogMessagecase class StringMessage(message:String) extends LogMessagecase class ExceptionMessage(exception:Throwable) extends LogMessagecase class BothMessage(message:String, exception:Throwable) extends LogMessage class Logger { def debug(l:LogMessage) = log(10,l) def info(l:LogMessage) = log(5,l) def error(l:LogMessage) = log(1,l) def log(level:Int, l:LogMessage): Unit = l match { case StringMessage(msg) => println(msg) case ExceptionMessage(exception:Error) => exception.printStackTrace }}

Page 19: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Pattern matching (cont.)

Author: Gal Lalouche - Technion 2015 ©

19

Functional progamming

Regular expressions

Much more…

def contains[T](list: List[T], x: T): Boolean { case Nil => false case e :: xs => if (e == x) true else contains(xs, x)}

val Name = new Regex("""(\w+)\s+(\w+)""")"Gal Lalouche" match { case Name(firstName, lastName) => println(firstName + " " + lastName) case _ => println("No match")}

Page 20: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Thing we don’t have time to cover

Author: Gal Lalouche - Technion 2015 ©

20

We only scratched the surface

Implicit methods

Implicit parameters

For comprehensions

Lazy evaluations

Views (similar to stream, but lazier)

Actors (expressive distributed model)

Much, much more…

Page 21: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

If you want to know more…

Author: Gal Lalouche - Technion 2015 ©

21

Suggested Reading:

Programming in Scala (The de-facto guide)

Scala in Depth

See more here: http://www.scala-lang.org/documentation/books.html

Coursera: Functional Programming Principles in Scala (by the language creator)

Principles of Reactive Programming (advanced course, by the language creator and several API designers)

Page 22: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

So is Scala perfect?

Author: Gal Lalouche - Technion 2015 ©

22

No language is perfectScala takes the “everything but the kitchen sink” approachThis gives us great powerBut With Great Power, Comes Great Responsibility!

Page 23: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

So is Scala perfect? (cont.)

Author: Gal Lalouche - Technion 2015 ©

23

All java code looks pretty much the same There no macros, no extension methods, little to no

syntactic sugar (especially before Java 8) You always know where the method comes from

With the exception of static imports

This makes Java very verbose… …but also very simple to read

Page 24: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

“Too much syntactic sugar causes cancer of the semi-colons”

Author: Gal Lalouche - Technion 2015 ©

24

Scala has much built into the language (i.e., not part of a library)

Java‘s map:

Scala’s map:

// sum numbers 1 to 100var sum = 0; for (i <- to 100) sum += i(for (i <- 1 to 100) yield i) sum1.to(100).reduce((x: Int, y: Int) => x.+(y))1.to(100).reduce((x, y) => x + y)1 to 100 reduce (_ + _)

<R> Stream<R> map(Function<? super T,? extends R> mapper)

map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

Page 25: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

“Too much syntactic sugar causes cancer of the semi-colons” (cont.)

Author: Gal Lalouche - Technion 2015 ©

25

It is very easy to create DSLs in ScalaScalatest (a unit-testing framework)

The above code compilesBut what’s going on here? is should a method? is be? what is equal or in?

"A List" should "pop values in last-in-first-out order" in { val $ = new MutableList[Int] $ add 1 $ add 2 $ at 0 should be equal 1 $ at 1 should be equal 2 }

Page 26: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

“Too much syntactic sugar causes cancer of the semi-colons” (cont.)

Author: Gal Lalouche - Technion 2015 ©

26

You can define new control structures

You can create Python-like syntax

def unless(b: Boolean)(f: => Unit) { if (!b) f}//… unless(x < 10) { println("x >= 10")}

implicit def richBoolean(b: Boolean) = new { def or(other: Boolean) = b || other def and(other: Boolean) = b && other}if ((b or c) and d) { // …}

Page 27: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

“Too much syntactic sugar causes cancer of the semi-colons” (cont.)

Author: Gal Lalouche - Technion 2015 ©

27

ProcessBuilder API

Page 28: Scala Technion – Institute of Technology Software Design (236700) Based on slides by: Sagie Davidovich, Assaf Israel Author: Gal Lalouche - Technion 2015

Summary

Author: Gal Lalouche - Technion 2015 ©

28

Scala combines functional and object oriented approaches

It is lightweight and expressive, supports DSL with ease, and fully interoperable with Java

However, when a language let’s you do everything, developers also have to know everything Especially when working in teams

Syntactic sugar is cool when working alone, but can quickly get out of hand