Component Abstractions in Scala The Basics



Similar documents
Analyse et Conception Formelle. Lesson 5. Crash Course on Scala

Overview. Elements of Programming Languages. Advanced constructs. Motivating inner class example

Tutorial on Writing Modular Programs in Scala

HIGH PERFORMANCE BIG DATA ANALYTICS

Applications to Computational Financial and GPU Computing. May 16th. Dr. Daniel Egloff

Web development... the server side (of the force)

Crash Course in Java

Programming Language Rankings. Lecture 15: Type Inference, polymorphism & Type Classes. Top Combined. Tiobe Index. CSC 131! Fall, 2014!

Semester Review. CSC 301, Fall 2015

Free Java textbook available online. Introduction to the Java programming language. Compilation. A simple java program

Free Java textbook available online. Introduction to the Java programming language. Compilation. A simple java program

Fundamentals of Java Programming

Software and the Concurrency Revolution

: provid.ir

Scala Programming Language

Java SE 8 Programming

A Multi-layered Domain-specific Language for Stencil Computations

A Scala Tutorial for Java programmers

e ag u g an L g ter lvin v E ram Neal G g ro va P Ja

Scala Actors Library. Robert Hilbrich

The C Programming Language course syllabus associate level

Intro to scientific programming (with Python) Pietro Berkes, Brandeis University

Reactive Slick for Database Programming. Stefan Zeiger

Green-Marl: A DSL for Easy and Efficient Graph Analysis

How Scala Improved Our Java

core. Volume I - Fundamentals Seventh Edition Sun Microsystems Press A Prentice Hall Title ULB Darmstadt

HPC Wales Skills Academy Course Catalogue 2015

Scientific Computing Programming with Parallel Objects

Java Interview Questions and Answers

Virtual Machine Learning: Thinking Like a Computer Architect

CSE 373: Data Structure & Algorithms Lecture 25: Programming Languages. Nicki Dell Spring 2014

Efficient Parallel Graph Exploration on Multi-Core CPU and GPU

Poor Man's Type Classes

Chapter 6: Programming Languages

Redesigning the language for business logic in the Maconomy ERP system and automatic translation of existing code

opalang - Rapid & Secure Web Development

Lecture Data Types and Types of a Language

Java EE Web Development Course Program

Scalable and Reactive Programming for Semantic Web Developers

Java 6 'th. Concepts INTERNATIONAL STUDENT VERSION. edition

Software Engineering Techniques

History OOP languages Year Language 1967 Simula Smalltalk

CS 111 Classes I 1. Software Organization View to this point:

The Flink Big Data Analytics Platform. Marton Balassi, Gyula Fora" {mbalassi,

The Importance of Software License Server Monitoring

Glossary of Object Oriented Terms

Multi-GPU Load Balancing for Simulation and Rendering

General Introduction

Habanero Extreme Scale Software Research Project

Cache Database: Introduction to a New Generation Database

Tutorial: Getting Started

Parallel Databases. Parallel Architectures. Parallelism Terminology 1/4/2015. Increase performance by performing operations in parallel

Migration Scenario: Migrating Batch Processes to the AWS Cloud

HPC Deployment of OpenFOAM in an Industrial Setting

Chapter 15 Functional Programming Languages

The countdown problem

Dart a modern web language

PostgreSQL Functions By Example

The Needle Programming Language

The Decaffeinated Robot

Android Application Development Course Program

Big Data Storage, Management and challenges. Ahmed Ali-Eldin

Computing Concepts with Java Essentials

Comp 411 Principles of Programming Languages Lecture 34 Semantics of OO Languages. Corky Cartwright Swarat Chaudhuri November 30, 20111

The Sun Certified Associate for the Java Platform, Standard Edition, Exam Version 1.0

Web Development in Java

CS11 Java. Fall Lecture 7

A Technical Review of TIBCO Patterns Search

Java SE 7 Programming

Programming Languages

Compiling Object Oriented Languages. What is an Object-Oriented Programming Language? Implementation: Dynamic Binding

Java Programming Language

GTask Developing asynchronous applications for multi-core efficiency

Monitoring Hadoop with Akka. Clint Combs Senior Software Engineer at Collective

Visualizing Software Projects in JavaScript

What Is Datacenter (Warehouse) Computing. Distributed and Parallel Technology. Datacenter Computing Application Programming

SMock A Test Platform for the Evaluation of Monitoring Tools

Openbus Documentation

Service Oriented Architecture

AP Computer Science Java Subset

iservdb The database closest to you IDEAS Institute

CSC408H Lecture Notes

DIPLOMADO DE JAVA - OCA

Scaling Up & Out with Actors: Introducing Akka

language 1 (source) compiler language 2 (target) Figure 1: Compiling a program

The Advantages and Disadvantages of Network Computing Nodes

Parallelism and Cloud Computing

MA-WA1920: Enterprise iphone and ipad Programming

Architectures for massive data management

PROBLEM SOLVING SEVENTH EDITION WALTER SAVITCH UNIVERSITY OF CALIFORNIA, SAN DIEGO CONTRIBUTOR KENRICK MOCK UNIVERSITY OF ALASKA, ANCHORAGE PEARSON

by Mario Fusco Monadic

Programming models for heterogeneous computing. Manuel Ujaldón Nvidia CUDA Fellow and A/Prof. Computer Architecture Department University of Malaga

David Rioja Redondo Telecommunication Engineer Englobe Technologies and Systems

Transcription:

Component Abstractions in Scala The Basics LASER Summer School, 2012 Martin Odersky Typesafe and EPFL

A Paradigm Shift The world of software is changing because of hardware trends. Moore s law now achieved by increasing # of cores not clock cycles Huge volume workloads that require horizontal scaling Data from Kunle Olukotun, Lance Hammond, Herb Sutter, Burton Smith, Chris Batten, and Krste Asanovic 2

Concurrent Programming to the Today, an often heard answer is concurrent programming, using Threads and locks, Actors with messages, or Agents, or STM All these concepts are useful and essential for many apps. But they alone will not solve the PPP Challenge. Fundamental problem: non-determinism Rescue? Leads to Heisenbugs, different behavior on different hardware, etc class Person(val name:string, val age: Int) new Actor { def receive = { case people: Set[Person] => val (minors, adults) = people partition (_.age < 18) Facebook! minors LinkedIn! adults 3

The Root of the Problem Non-determinism caused by concurrent threads accessing shared mutable state. We can encapsulate state in actors or transactions, but the fundamental problem is the same. var x = 0 async { x = x + 1 async { x = x * 2 // can give 0, 1, 2 So, non-determinism = parallel processing + mutable state To get deterministic processing, avoid the mutable state! Avoiding mutable state means programming functionally 4

Space vs Time Space (functional/parallel) Time (imperative/concurrent) 5

What about Objects? So, should we forget OO and all program in functional programming languages? No! What the industry learned about OO decomposition in analysis and design stays valid. Central question: What goes where? In the end, need to put things somewhere, or risk unmanageable global namespace. 6

New Objects Previously: Objects are characterized by state, identity, and behavior. (Booch) Now: Eliminate or reduce mutable state. Structural equality instead of reference identity. Concentrate on functionality (behavior) 7

New Objects What about: Tell, don t ask.? This advice is due to the Von-Neumann bottleneck (Backus), i.e. the tendency to communicate with small, primitive values. Now: Ask to construct 8

Scala: An object-functional language Scala has established itself as one of the main alternative languages on the JVM. Prehistory: 1996 1997: Pizza 1998 2000: GJ, Java generics, javac ( make Java better ) Timeline: 2003 2006: The Scala Experiment 2006 2009: An industrial strength programming language ( make a better Java ) 1-9

Scala Community Community growing 100%+ annually 25+ books 60+ active user groups Sold out Scala Days conference with 400 attendees, 60+ talks job trends on indeed.com 10

Github vs. Stack Overflow RedMonk: Revisiting the Dataists Programming Language Rankings Typesafe Confidential 11

Select Commercial Users Migrated core messaging service from Ruby to Scala to sustain 3 orders of magnitude growth Scala drives the core LinkedIn social graph service with 400+ million transactions per day "Nearly our entire server codebase is written in Scala. This has worked out super well." With Akka we deliver systems that meet the most strict performance requirements in a near-realtime environment.

Scala cheat sheet (1): Definitions Scala method definitions: def fun(x: Int): Int = { result or def fun(x: Int) = result def fun = result Java method definition: int fun(int x) { return result; (no parameterless methods) Scala variable definitions: var x: Int = expression val x: String = expression or var x = expression val x = expression Java variable definitions: int x = expression final String x = expression 2-13

Scala cheat sheet (2): Expressions Scala method calls: obj.meth(arg) or obj meth arg Scala choice expressions: if (cond) expr1 else expr2 expr match { case pat 1 => expr 1... case pat n => expr n Java method call: obj.meth(arg) (no operator overloading) Java choice expressions, stats: cond? expr1 : expr2 if (cond) return expr1; else return expr2; switch (expr) { case pat 1 : return expr 1 ;... case pat n : return expr n ; // statement only 2-14

Scala cheat sheet (3): Objects and Classes Scala Class and Object Java Class with static class Sample(x: Int) { def instmeth(y: Int) = x + y object Sample { def staticmeth(x:int, y:int) = x * y class Sample { final int x; Sample(int x) { this.x = x int instmeth(int y) { return x + y; static int staticmeth(int x,int y) { return x * y; 2-15

Scala cheat sheet (4): Traits Scala Trait trait T { def absmeth(x:string):string def concretemeth(x: String) = x+field Java Interface interface T { String absmeth(string x) (no concrete methods) var field =! (no fields) Scala mixin composition: class C extends Super with T Java extension + implementation: class C extends Super implements T 2-16

Scala cheat sheet (5): Packages and Imports Scala Package Clause Java Package Clause package org.project.module package org.project.module; or package org.project package module Scala Import Java import import collection.mutable.map import collection.mutable._ import collection.mutable.{ Map => mmap import collection.mutable.map; import collection.mutable.*; (no import renaming) 2-17

Scala s Type Hierarchy 2-18

Top Types: Any, AnyRef, AnyVal Any The base type of all types Methods: ==,!=, equals ##, hashcode tostring asinstanceof isinstanceof AnyRef The base type of all reference types, alias of java.lang.object Methods: eq, ne AnyVal The base types of all value types 2-19

The Nothing Type Nothing is a type without any values. Why is that useful? To signal abnormal termination: throw new Error() has type Nothing As an element of empty collections. The two meanings hang together: Taking an element of a List[Nothing] has type Nothing, and will not terminate normally. 2-20

The Null Type The null value also has a type in Scala; it is called Null scala> val x = null x: Null = null Null is a subtype of every reference type in Scala, but it is not compatible with value types. scala> val x: String = null x: String = null scala> val x: Int = null <console>:7: error: type mismatch; found : Null(null) required: Int val x: Int = null ^ 2-21

A Closer Look at Collections De-emphasize destructive updates Focus on transformers that map collections to collections Have a complete range of immutable, persistent collections scala> val ys = List(1, 2, 3) ys: List[Int] = List(1, 2, 3) scala> val xs: Seq[Int] = ys xs: Seq[Int] = List(1, 2, 3) scala> xs map (_ + 1) res0: Seq[Int] = List(2, 3, 4) scala> ys map (_ + 1) res1: List[Int] = List(2, 3, 4) 13

Using Collections: Map and filter scala> val xs = List(1, 2, 3) xs: List[Int] = List(1, 2, 3) scala> val ys = xs map (x => x + 1) ys: List[Int] = List(2, 3, 4) scala> val ys = xs map (_ + 1) ys: List[Int] = List(2, 3, 4) scala> val zs = ys filter (_ % 2 == 0) zs: List[Int] = List(2, 4) scala> val as = ys map (0 to _) as: List(Range(0, 1, 2), Range(0, 1, 2, 3), Range(0, 1, 2, 3, 4)) 23

Using Collections: flatmap and groupby scala> val bs = as.flatten bs: List[Int] = List(0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4) scala> val bs = ys flatmap (0 to _) bs: List[Int] = List(0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4) scala> val fruit = Vector("apple", pear", pineapple") fruit: Vector[String] = Vector(apple, pear, pineapple) scala> fruit groupby (_.head) res11: scala.collection.immutable.map[char,vector[string]] = Map(a -> Vector(apple), p -> Vector(pear, pineapple)) 24

Using Collections: For Notation scala> for (x <- xs) yield x + 1 res14: List[Int] = List(2, 3, 4) // same as map scala> for (x <- res14 if x % 2 == 0) yield x res15: List[Int] = List(2, 4) // ~ filter scala> for (x <- xs; y <- 0 to x) yield y res17: List[Int] = List(0, 1, 0, 1, 2, 0, 1, 2, 3) // same as flatmap 25

Using Maps scala> val m = Map(1 -> "ABC", 2 -> "DEF", 3 -> "GHI") m: Map[Int, String] = Map(1 -> ABC, 2 -> DEF, 3-> GHI) scala> m(2) res0: String = DEF scala> m + (4 -> "JKL") res1: Map[Int, String] = Map(1 -> ABC, 2 -> DEF, 3 -> GHI, 4 -> JKL) scala> m map { case (k, v) => (v, k) res8: Map[String,Int] = Map(ABC -> 1, DEF -> 2, GHI -> 3) 26

An Example Task: Phone keys have mnemonics assigned to them. val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") Assume you are given a dictionary dict as a list of words. Design a class Coder with a method translate such that new Coder(dict).translate(phoneNumber) produces all phrases of words in dict that can serve as mnemonics for the phone number. Example: The phone number 7225276257 should have the mnemonic Scala rocks as one element of the list of solution phrases. 27

Program Example: Phone Mnemonics This example was taken from: Lutz Prechelt: An Empirical Comparison of Seven Programming Languages. IEEE Computer 33(10): 23-29 (2000) Tested with Tcl, Python, Perl, Rexx, Java, C++, C Code size medians: 100 loc for scripting languages 200-300 loc for the others 28

Outline of Class Coder class Coder(words: List[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] =?? /** Maps a word to the digit string it can represent, e.g. Java -> 5282 */ private def wordcode(word: String): String =?? /** A map from digit strings to the words that represent them, * e,g. 5282 -> Set( Java, Kata, Lava,...) */ private val wordsfornum: Map[String, Set[String]] =?? /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] =?? /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 29

Class Coder (1) class Coder(words: List[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] = /** Maps a word to the digit string it can represent */ private def wordcode(word: String): String =?? /** A map from digit strings to the words that represent them */ private val wordsfornum: Map[String, List[String]] =?? /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] =?? /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 30

Class Coder (1) class Coder(words: List[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] = for ((digit, str) <- mnemonics; ltr <- str) yield (ltr -> digit) /** Maps a word to the digit string it can represent */ private def wordcode(word: String): String =?? /** A map from digit strings to the words that represent them */ private val wordsfornum: Map[String, List[String]] =?? /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] =?? /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 31

Class Coder (2) class Coder(words: List[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] = for ((digit, str) <- m; letter <- str) yield (letter -> digit) /** Maps a word to the digit string it can represent, e.g. Java -> 5282 */ private def wordcode(word: String): String = /** A map from digit strings to the words that represent them */ private val wordsfornum: Map[String, Set[String]] =?? /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] =?? /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 32

Class Coder (2) class Coder(words: List[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] = for ((digit, str) <- m; letter <- str) yield (letter -> digit) /** Maps a word to the digit string it can represent, e.g. Java -> 5282 */ private def wordcode(word: String): String = word.touppercase map charcode /** A map from digit strings to the words that represent them */ private val wordsfornum: Map[String, Set[String]] =?? /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] =?? /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 33

Class Coder (3) class Coder(words: List[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] = for ((digit, str) <- m; letter <- str) yield (letter -> digit) /** Maps a word to the digit string it can represent */ private def wordcode(word: String): String = word.touppercase map charcode /** A map from digit strings to the words that represent them, * e,g. 5282 -> Set( Java, Kata, Lava,...) */ private val wordsfornum: Map[String, List[String]] = /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] =?? /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 34

Class Coder (3) class Coder(words: List[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] = for ((digit, str) <- m; letter <- str) yield (letter -> digit) /** Maps a word to the digit string it can represent */ private def wordcode(word: String): String = word.touppercase map charcode /** A map from digit strings to the words that represent them, * e,g. 5282 -> Set( Java, Kata, Lava,...) */ private val wordsfornum: Map[String, List[String]] = (words groupby wordcode) withdefaultvalue Nil /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] =?? /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 35

Class Coder (4) class Coder(words: List[String]) {... /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] = /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 36

Class Coder (4) class Coder(words: List[String]) {... /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] = if (number.isempty) Set(List()) /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 37

Class Coder (4) class Coder(words: List[String]) {... /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] = if (number.isempty) Set(List()) else { for { splitpoint <- 1 to number.length /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 38

Class Coder (4) class Coder(words: List[String]) {... /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] = if (number.isempty) Set(List()) else { for { splitpoint <- 1 to number.length word <- wordsfornum(number take splitpoint) /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 39

Class Coder (4) class Coder(words: List[String]) {... /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] = if (number.isempty) Set(List()) else { for { splitpoint <- 1 to number.length word <- wordsfornum(number take splitpoint) rest <- encode(number drop splitpoint) yield word :: rest.toset /** Maps a number to a list of all word phrases that can represent it */ def translate(number: String): Set[String] = encode(number) map (_ mkstring " ") 40

A solution in Java by the expert 41

Going Further In Scala 2.9, collections support parallel operations. Two new methods: c.par returns parallel version of collection c c.seq returns sequential version of collection c The right tool for addressing the PPP (popular parallel programming) challenge. I expect this to be the cornerstone for making use of multicores for the rest of us. 42

a parallel collection Parallel Coder class Coder(words: ParVector[String]) { private val mnemonics = Map( '2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ") /** Invert the mnemonics map to give a map from chars 'A'... 'Z' to '2'... '9' */ private val charcode: Map[Char, Char] = for ((digit, str) <- m; letter <- str) yield (letter -> digit) /** Maps a word to the digit string it can represent */ private def wordcode(word: String): String = word.touppercase map charcode /** A map from digit strings to the words that represent them */ private val wordsfornum: Map[String, List[String]] = words groupby wordcode /** Return all ways to encode a number as a list of words */ def encode(number: String): Set[List[String]] = if (number.isempty) Set(List()) else { for { splitpoint <- (1 to number.length).par word <- wordsfornum(number take splitpoint) rest <- encode(number drop splitpoint) yield word :: rest.toset mapping sequential collection to parallel 43

Parallel Collections Split work by number of Processors Each Thread has a work queue that is split exponentially. Largest on end of queue Granularity balance against scheduling overhead On completion threads work steals from end of other thread queues

In Summary In the original experiment: Scripting language programs were shorter and often even faster than Java/C/C++ because their developers tended to use standard collections. In Scala s solution: Obtained a further 5x reduction in size because of the systematic use of functional collections. Scala s collection s are also easily upgradable to parallel. Think collection transformers, not CRUD! 45

The Future Scala s persistent collections are easy to use: concise: safe: fast: universal: few steps to do the job one word replaces a whole loop type checker is really good at catching errors collection ops are tuned, can be parallelized one vocabulary to work on all kinds of collections We see them play a rapidly increasing role in software development.

But how is all this implemented? 47

Everything is a Library Collections feel like they are an organic part of Scala But in fact the language does not contain any collectionrelated constructs no collection types no collection literals no collection operators Everything is done in a library Everything is extensible You can write your own collections which look and feel like the standard ones 48

The Uniform Return Type Principle Bulk operations return collections of the same type (constructor) as their left operand. (DWIM) scala> val ys = List(1, 2, 3) ys: List[Int] = List(1, 2, 3) scala> val xs: Seq[Int] = ys xs: Seq[Int] = List(1, 2, 3) scala> xs map (_ + 1) res0: Seq[Int] = List(2, 3, 4) scala> ys map (_ + 1) res1: List[Int] = List(2, 3, 4) This is tricky to implement without code duplication! 49

Pre 2.8 Collection Structure trait Iterable[A] { def filter(p: A => Boolean): Iterable[A] =... def partition(p: A => Boolean) = (filter(p(_)), filter(!p(_))) def map[b](f: A => B): Iterable[B] =... trait Seq[A] extends Iterable[A] { def filter(p: A => Boolean): Seq[A] =... override def partition(p: A => Boolean) = (filter(p(_)), filter(!p(_))) def map[b](f: A => B): Seq[B] =... 50

Types force duplication filter needs to be re-defined on each level partition also needs to be re-implemented on each level, even though its definition is everywhere the same. The same pattern repeats for many other operations and types. ideal conditions for Bit Rot 51

Signs of Bit Rot Lots of duplications of methods. Methods returning collections have to be repeated for every collection type. Inconsistencies. Sometimes methods such as filter, map were not specialized in subclasses More often, they only existed in subclasses, even though they could be generalized Broken window effect. Classes that already had some ad-hoc methods became dumping grounds for lots more. Classes that didn t stayed clean. 52

Excerpts from List.scala 4-53

How to do better? Can we abstract out the return type? Look at map: Need to abstract out the type constructor, not just the type. trait Iterable[A] def map[b](f: A => B): Iterable[B] trait Seq[A] def map[b](f: A => B): Seq[B] But we can do that using Scala s higher-kinded types! 54

HK Types Collection Structure trait TraversableLike[A, CC[X]] { def filter(p: A => Boolean): CC[A] def map[b](f: A => B): CC[B] trait Traversable[A] extends TraversableLike[A, Traversable] trait Iterable[A] trait Seq[A] extends TraversableLike[A, Iterable] extends TraversableLike[A, Seq] Here, CC is a parameter representing a type constructor. 55

Implementation with Builders All ops in Traversable are implemented in terms of foreach and newbuilder. trait Builder[A, Coll] { def += (elem: A) // add elems def result: Coll // return result trait TraversableLike[A, CC[X]] { def foreach(f: A => Unit) def newbuilder[b]: Builder[B, CC[B]] def map[b](f: A => B): CC[B] = { val b = newbuilder[b] foreach (x => b += f(x)) b.result 56

Unfortunately...... things are not as parametric as it seems at first. Take: class BitSet extends Set[Int] scala> val bs = BitSet(1, 2, 3) bs: scala.collection.immutable.bitset = BitSet(1, 2, 3) scala> bs map (_ + 1) res0: scala.collection.immutable.bitset = BitSet(2, 3, 4) scala> bs map (_.tostring + "!") res1: scala.collection.immutable.set[java.lang.string] = Set(1!, 2!, 3!) Note that the result type is the best possible type that fits the element type of the new collection. Other examples: SortedSet, String, Array 57

How to advance? We need more flexibility. Can we define our own type system for collections? Question: Given old collection type From, new element type Elem, and new collection type To: Can an operation on From build a collection of type To with Elem elements? Captured in: CanBuildFrom[From, Elem, To] 58

Facts about CanBuildFrom Can be stated as axioms and inference rules: CanBuildFrom[Traversable[A], B, Traversable[B]] CanBuildFrom[Set[A], B, Set[B]] CanBuildFrom[BitSet, B, Set[B]] CanBuildFrom[BitSet, Int, BitSet] CanBuildFrom[String, Char, String] CanBuildFrom[String, B, Seq[B]] CanBuildFrom[SortedSet[A], B, SortedSet[B]] :- Ordering[B] where A and B are arbitrary types. 59

Implicitly Injected Theories Type theories such as the one for CanBuildFrom can be injected using implicits. A predicate: trait CanBuildFrom[From, Elem, To] { def apply(coll: From): Builder[Elem, To] Axioms: implicit def bf1[a, B]: CanBuildFrom[Traversable[A], B, Traversable[B]] implicit def bf2[a, B]: CanBuildFrom[Set[A], B, Set[B]] implicit def bf3: CanBuildFrom[BitSet, Int, BitSet] Inference rule: implicit def bf4[a, B] (implicit ord: Ordering[B]) : CanBuildFrom[SortedSet[A], B, SortedSet[B]] 60

Connecting with Map Here s how map can be defined in terms CanBuildFrom: trait TraversableLike[A, Coll] { this: Coll => def foreach(f: A => Unit) def newbuilder: Builder[A, Coll] def map[b, To](f: A => B) (implicit cbf: CanBuildFrom[Coll, B, To]): To = { val b = cbf(this) foreach (x => b += f(x)) b.result 61

Objections 62

4-63

Use Cases How to explain def map[b, To](f: A => B) (implicit cbf: CanBuildFrom[Coll, B, To]): To to a beginner? Key observation: We can approximate the type of map. For everyone but the most expert user def map[b](f: A => B): Traversable[B] // in class Traversable def map[b](f: A => B): Seq[B] // in class Seq, etc is detailed enough. These types are correct, they are just not as general as the type that s actually implemented. 64

Part of the Solution: Flexible Doc Comments 65

Going even further But how do we keep a bunch of Fermi s happy? How to find and deal with 10000+ threads in an application? Parallel collections are necessary but not sufficient for this. Our bet for the future: parallel embedded DSLs. Find parallelism in domains: machine learning, simulation, statistics,... Joint work with Kunle Olukuton, Pat Hanrahan @ Stanford. EPFL side funded by ERC. 66

EPFL / Stanford Research Applications Scientific Engineering Virtual Worlds Personal Robotics Data informatics Domain Specific Languages Rendering Physics (Liszt) Scripting Probabilistic (RandomT) Machine Learning (OptiML) Domain Embedding Language (Scala) DSL Infrastructure Polymorphic Embedding Staging Static Domain Specific Opt. Parallel Runtime (Delite, Sequoia, GRAMPS) Dynamic Domain Spec. Opt. Task & Data Parallelism Locality Aware Scheduling Heterogeneous Hardware Hardware Architecture OOO Cores SIMD Cores Threaded Cores Specialized Cores Programmable Hierarchies Scalable Coherence Isolation & Atomicity On-chip Networks Pervasive Monitoring 67

Example: Liszt - A DSL for Physics Simulation Turbulence Combustion Mesh-based Numeric Simulation Huge domains millions of cells Transition Turbulence Example: Unstructured Reynolds-averaged Navier Stokes (RANS) solver Fuel injection Thermal 68

Liszt as Virtualized Scala val // calculating scalar convection (Liszt) val Flux = new Field[Cell,Float] val Phi = new Field[Cell,Float] val cell_volume = new Field[Cell,Float] val deltat =.001... untilconverged { for(f <- interior_faces) { val flux = calc_flux(f) Flux(inside(f)) -= flux Flux(outside(f)) += flux for(f <- inlet_faces) { Flux(outside(f)) += calc_boundary_flux(f) for(c <- cells(mesh)) { Phi(c) += deltat * Flux(c) /cell_volume(c) for(f <- faces(mesh)) Flux(f) = 0.f DSL Library AST Optimisers Generators Schedulers Hardware GPU, Multi-Core, etc 69