Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo

1

A Scalable Language Martin Odersky FOSDEM 2009

2

The software landscape today … …  resembles a tower of Babel with many little (or not so little) languages playing together. E.g. JavaScript  on the client Perl/Python/Ruby/Groovy  for server side scripting JavaFX  for the UI Java  for the business logic SQL  for database access all cobbled together with a generous helping of XML.

3

This is both good and bad Good : Every language can concentrate on what it’s best at. Bad : Cross language communication:    complicated, fragile, source of misunderstandings. Problematic : Cross language communication is controlled by a common type system (neither static nor dynamic). It's based on low-level representations such as XML trees or (worse) strings (as in JDBC database queries).

4

Alternative: Scalable languages A language is  scalable  if it is suitable for very small as well as very large programs. A single language for extension scripts and the heavy lifting. Application-specific needs are handled through libraries and embedded DSL's instead of external languages. Scala shows that this is possible.

5

Scala is a scripting language It has an interactive read-eval-print-loop (REPL). Types can be inferred. Boilerplate is scrapped. scala>  var capital = Map("US"    "Washington", "France"    "Paris") capital: Map[String, String] = Map(US    Washington, France    Paris) scala>  capital += ("Japan"    "Tokio") scala>  capital("France") res7: String = Paris

6

Scala is the Java of the future It has basically everything Java has now. (sometimes in different form) It has closures.  (proposed for Java 7, but rejected) It has traits and pattern matching. (I would not be surprised to see them in Java 8, 9 or 10) It compiles to .class files, is completely interoperable and runs about as fast as Java object   App  {    def   main ( args :  Array [ String ]) {    if  ( args   exists  (_. toLowerCase   ==   "-help" ))    printUsage ()   else     process ( args )   } }

7

Interoperability Scala fits seamlessly into a Java environment Can call Java methods, select Java fields, inherit Java classes, implement Java interfaces, etc. None of this requires glue code or interface descriptions Java code can also easily call into Scala code Scala code resembling Java is translated into virtually the same bytecodes.    Performance is usually on a par with Java

8

Scala is a composition language New approach to module systems: component = class or trait composition via mixins Abstraction through parameters, abstract members (both types and values), self types gives  dependency injection  for free trait  Analyzer {  this : Backend =>   … } trait   Backend   extends   Analyzer   with   Optimization   with   Generation  { val   global :  Main     import   global ._ type   OutputMedium  <:  Writable   }

9

Is Scala a “kitchen-sink language”? Not at all. In terms of feature count, Scala is roughly comparable to today’s Java and smaller than C# or C++.  But Scala is  deep , where other languages are  broad . Two principles:  1.  Focus on abstraction and composition, so that users can implement their own specialized features as needed. 2. Have the same sort of constructs work for very small as well as very large programs.

10

Scala compared to Java Modeled   in libraries:   assert, enums, properties, events, actors, using, queries, … raw types + abstract types Scala removes Scala adds - wildcards + existential types enums + pattern matching - special treatment of interfaces + mixin composition with traits - break, continue + closures  - primitive types + operator overloading - static members + a pure object system

11

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

12

Scala cheat sheet (2): Expressions Scala  method calls: obj.meth(arg) 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, stmts:  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

13

Scala cheat sheet (3): Objects and Classes Scala  Class and Object class  Sample(x: Int,  val  p: Int) {   def  instMeth(y: Int) = x + y } object  Sample {   def  staticMeth(x: Int, y: Int) =    x * y } Java  Class with statics class  Sample { private   final int  x; public final int  p;  Sample( int  x,  int  p) {    this.x = x;    this.p = p; }   int  instMeth( int  y) {    return  x + y;    }    static   int  staticMeth( int  x,  int  y) {   return  x * y;   } }

14

Scala cheat sheet (4): Traits Scala  Trait trait  T { def  abstractMth(x: String): Int def  concreteMth(x: String) = x + field var  field = “!” } Scala  mixin composition: class  C  extends  Super  with  T   Java  Interface interface  T {   int  abstractMth(String x) } (no concrete methods) (no fields)   Java   extension + implementation: class  C  extends  Super  implements  T

15

Spring Cleaning Scala’s syntax is  lightweight and concise.  Due to: semicolon inference, type inference, lightweight classes, extensible API’s, closures as control abstractions. Average reduction in LOC: ≥ 2   due to concise syntax and better abstraction capabilities        Scala feels like a cleaned up Java … var   capital  =  Map ( &quot;US&quot;   ->   &quot;Washington&quot; ,  &quot;Canada&quot;   ->   &quot;ottawa&quot; ) capital  += ( &quot;Japan&quot;  ->  &quot;Tokyo&quot; ) for  (c <- capital.keys) capital(c) = capital(c).capitalize assert(capital( &quot;Canada&quot; ) ==  &quot;Ottawa&quot; )

16

… with one major difference It's  x: Int   instead of   int x Why the change? Works better with type inference: var  x = 0   instead of   x = 0   // that's not a definition! Works better for large type expressions: val  x: HashMap[String, (String, List[Char])] = …   instead of public final  HashMap<String, Pair<String, List<Char>>> x = …

17

Scalability demands extensibility Take numeric data types Today's languages support  int, long, float, double . Should they also support  BigInt, BigDecimal, Complex, Rational, Interval, Polynomial ? There are good reasons for each of these types But a language combining them all would be too complex. Better alternative: Let users  grow  their language according to their needs.

18

Adding new datatypes - seamlessly For instance type  BigInt : def   factorial ( x :  BigInt ):  BigInt  =    if  ( x   ==  0) 1  else   x   *   factorial ( x   -  1) Compare with using Java's class: import  java.math.BigInteger def   factorial ( x :  BigInteger ):  BigInteger  =   if  ( x   ==  BigInteger.ZERO)   BigInteger . ONE   else   x . multiply (factorial(x.subtract(BigInteger.ONE))) }

19

Implementing new datatypes - seamlessly Here's how BigInt is implemented import  java.math.BigInteger class   BigInt ( val   bigInteger :  BigInteger )  extends   java . lang . Number  { def   +  ( that :  BigInt ) =    new   BigInt ( this . bigInteger   add   that . bigInteger ) def   -  ( that :  BigInt ) =    new   BigInt ( this . bigInteger   subtract   that . bigInteger ) …  // other methods implemented analogously } +  is an identifier; can be used as a method name Infix operations are method calls: a + b   is the same as  a.+(b) a add b   is the same as  a.add(b)

20

Adding new control structures  For instance  using  for resource control  (proposed for Java 7) Instead of: using  ( new   BufferedReader ( new   FileReader ( path ))) {   f  =>  println ( f . readLine ()) } val   f  =  new   BufferedReader ( new   FileReader ( path )) try  {   println ( f . readLine ()) }  finally  {   if  ( f   !=   null )  f . close () }

21

Implementing new control structures: Here's how one would go about implementing  using : def   using [ T  <: {  def   close () }]   ( resource :  T )   ( block :  T  =>  Unit ) {   try  {   block ( resource )   }  finally  {   if  ( resource   !=   null )  resource . close ()   } } T  is a type parameter... … supporting a  close   method A closure that takes a  T   parameter

22

Break and continue Scala does not have them. Why? They are a bit imperative; better use many smaller functions. Issues how to interact with closures. They are not needed! We can support them purely in the libraries. import  scala.util.control.Breaks._ breakable {   for  (x <- elems) {   println(x * 2)   if (x > 0) break   } }

23

Getting back break and continue

24

What makes Scala scalable? Many factors: strong typing, inference, little boilerplate,… But mainly, its tight integration of functional and object-oriented programming Functional programming:  Makes it easy to build interesting  things from simple parts, using higher-order functions, algebraic types and    pattern matching, parametric polymorphism. Object-oriented programming:   Makes it easy to adapt and extend  complex systems, using subtyping and inheritance, dynamic configurations, classes as partial abstractions.

25

Scala is object-oriented Every value is an object Every operation is a method call Exceptions to these rules in Java (such as primitive types, statics) are eliminated. scala>  (1).hashCode res8: Int = 1 scala>  (1).+(2) res10: Int = 3

26

Scala is functional Scala is a functional language, in the sense that every function is a value. Functions can be anonymous, curried, nested. Many useful higher-order functions are implemented as methods of Scala classes. E.g:  scala>  val matrix = Array(Array(1, 0, 0),     |  Array(0, 1, 0),    |  Array(0, 0, 1)) matrix: Array[Array[Int]] = Array([I@164da25,…  scala>  matrix.exists(row => row.forall(0 ==)) res13: Boolean = false

27

Functions  are  objects If functions are values, and values are objects, it follows that functions themselves are objects. The function type  S => T  is equivalent  to  scala.Function1[S, T],  where  Function1  is defined as follows: So functions are interpreted as objects with apply methods. For example, the  anonymous successor  function  (x: Int ) => x + 1   is expanded to: trait   Function1 [ -S ,  +T ] {   def   apply ( x :  S ):  T } new   Function1 [ Int ,  Int ] {   def   apply ( x :  Int ) =    x   +  1 }

28

Why should I care? Since ( => ) is a class, it can be subclassed. So one can  specialize  the concept of a function. An obvious use is for arrays, which are mutable functions over integer ranges. A bit of syntactic sugaring lets one write: a(i) = a(i) + 2   for a.update(i, a.apply(i) + 2) class   Array  [ T ] ( l :  Int ) extends  ( Int  =>  T ) { def   length :  Int  = l def   apply ( i :  Int ):  T  = … def   update ( i :  Int ,  x :  T ): Unit def   elements :  Iterator [ T ] def   exists ( p :  T  =>  Boolean ) … }

29

Partial functions Another useful abstraction are partial functions. These are functions that are defined only in some part of their domain. What's more, one can inquire with the  isDefinedAt  method whether a partial function is defined for a given value. Scala treats blocks of pattern matching cases as instances of partial functions. This lets one write control structures that are not easily expressible otherwise. trait   PartialFunction [- A , + B ] extends  ( A  =>  B ) { def   isDefinedAt ( x :  A ): Boolean }

30

Developing new paradigms Scala's flexibility makes it possible for users to grow the language into completely new paradigms. Case in point: concurrent programming Since Scala is interoperable, Java threads and concurrent libraries are available. But it's also possible to explore completely new paradigms.

31

Erlang-style actors Two principal constructs (adopted from Erlang): Send ( ! ) is asynchronous; messages are buffered in an actor's mailbox. receive  picks the first message in the mailbox which matches any of the patterns  msgpat i . If no pattern matches, the actor suspends. // asynchronous message send actor   !   message // message receive receive  { case   msgpat 1  => action 1 …  case   msgpat n  => action n } A pattern matching block of type PartialFunction[ MessageType ,  ActionType ]

32

A simple actor case   class   Data ( bytes :  Array [ Byte ]) case   class   Sum ( receiver :  Actor ) val   checkSumCalculator  =  actor  { var  sum = 0 loop  { receive  { case   Data ( bs ) =>  sum   +=   hash ( bs ) case   Sum ( receiver ) =>  receiver   !   sum } } } } repeatedly  receive  messages Spawn a new actor

33

Implementing receive Using partial functions, it is straightforward to implement receive: Here, self designates the currently executing actor, mailBox   is its queue of pending messages, and extractFirst   extracts first queue element matching given predicate. def  receive  [ T ] ( f :  PartialFunction[Message ,  T ]): T = { self . mailBox . extractFirst ( f . isDefinedAt ) match { case  Some(msg ) =>  f ( msg ) case None => self . wait ( messageSent ) }}

34

Other Approaches to Scalability C++  Hard to scale down. Scaling up is possible for expert users. .NET Many languages with common interoperability. Hard to do something that's really different. Java Lingua franca  makes it easy to understand other people's code. Not easy to scale down or up    pressure to add new languages.

35

Where are we now? Scala Easy to scale down and up. Works well with a mix of expert users (for the framework) and non-experts (for the application code). Scala solves the expressiveness challenge for doing this. But does it also solve the safety issues? Problem: How to ensure that domain-specific code stays within its domain-specific library/language? For instance: How to ensure that a query formulated in Scala is non-recursive? Addressed by ongoing project:  Pluggable type systems

36

The Scala community 50000 downloads in 2008 300+ trak contributors  20+ messages/day on the mailing lists Industrial adoption has started, among others at:  Twitter, Sony Pictures, Nature.com, Reaktor, Mimesis Republic,  EDF Trading, … Scala LiftOff conference, May 2008. Scala talks in many conferences; next two at QCon, London, March 10-12.

37

Tool support Standalone compiler:  scalac Fast background compiler:  fsc Interactive interpreter shell and script runner:  scala Web framework:  lift Testing frameworks:  Specs, ScalaCheck, ScalaTest, SUnit, … IDE plugins for: Eclipse  (supported by EDF) IntelliJ  (supported by JetBrains) Netbeans  (supported by Sun)

38

Tool support Standalone compiler:  scalac Fast background compiler:  fsc Interactive interpreter shell and script runner:  scala Web framework:  lift Testing frameworks:  Specs, ScalaCheck, ScalaTest, SUnit, … IDE plugins for: Eclipse  (supported by EDF) IntelliJ  (supported by JetBrains) Netbeans  (supported by Sun)

39

Who’s using it? Open source projects:  lift wicket NetLogo  SPDE: Scala branch for Processing Isabelle: GUI and code extractor Companies: Twitter: infrastructure Sony Pictures: middleware Nature.com: infrastructure SAP community: ESME company messaging Reaktor: many different projects Mimesis Republic: multiplayer games EDF: trading, …

40

Learning Scala To get started: First steps in Scala, by Bill Venners  published in Scalazine at www.artima.com Scala for Java Refugees by Daniel Spiewack (great blog series) To continue: Programming in Scala, by  Odersky, Spoon, Venners, published by Artima,com Other books are in the pipeline.

41

Thank You To try it out: scala-lang.org Thanks also to the (past and present) members of the Scala team: Philippe Altherr, Vincent Cremet, Iulian Dragos, Gilles Dubochet, Burak Emir, Sebastian Hack, Philipp Haller, Sean McDirmid, Ingo Meier, Adriaan Moors, Stéphane Micheloud, Nikolay Mihaylov, Anders Nielssen, Tiark Rompf, Lukas Rytz, Michel Schinz, Lex Spoon, Erik Stenman, Geoffrey Alan Washburn, Matthias Zenger .

42

Relationship between Scala and other languages Main influences on the Scala design: Java, C# for their syntax, basic types, and class libraries, Smalltalk for its uniform object model, Eiffel for its uniform access principle, Beta for systematic nesting, ML, Haskell for many of the functional aspects. OCaml, OHaskel, PLT-Scheme, as other (less tightly integrated) combinations of FP and OOP. Pizza, Multi Java, Nice as other extensions of the Java platform with functional ideas. (Too many influences in details to list them all) Scala also seems to influence other new language designs, see for instance the closures and comprehensions in LINQ/C# 3.0.

More Related Content

Scala Talk at FOSDEM 2009

  • 1. A Scalable Language Martin Odersky FOSDEM 2009
  • 2. The software landscape today … … resembles a tower of Babel with many little (or not so little) languages playing together. E.g. JavaScript on the client Perl/Python/Ruby/Groovy for server side scripting JavaFX for the UI Java for the business logic SQL for database access all cobbled together with a generous helping of XML.
  • 3. This is both good and bad Good : Every language can concentrate on what it’s best at. Bad : Cross language communication: complicated, fragile, source of misunderstandings. Problematic : Cross language communication is controlled by a common type system (neither static nor dynamic). It's based on low-level representations such as XML trees or (worse) strings (as in JDBC database queries).
  • 4. Alternative: Scalable languages A language is scalable if it is suitable for very small as well as very large programs. A single language for extension scripts and the heavy lifting. Application-specific needs are handled through libraries and embedded DSL's instead of external languages. Scala shows that this is possible.
  • 5. Scala is a scripting language It has an interactive read-eval-print-loop (REPL). Types can be inferred. Boilerplate is scrapped. scala> var capital = Map(&quot;US&quot;  &quot;Washington&quot;, &quot;France&quot;  &quot;Paris&quot;) capital: Map[String, String] = Map(US  Washington, France  Paris) scala> capital += (&quot;Japan&quot;  &quot;Tokio&quot;) scala> capital(&quot;France&quot;) res7: String = Paris
  • 6. Scala is the Java of the future It has basically everything Java has now. (sometimes in different form) It has closures. (proposed for Java 7, but rejected) It has traits and pattern matching. (I would not be surprised to see them in Java 8, 9 or 10) It compiles to .class files, is completely interoperable and runs about as fast as Java object App { def main ( args : Array [ String ]) { if ( args exists (_. toLowerCase == &quot;-help&quot; )) printUsage () else process ( args ) } }
  • 7. Interoperability Scala fits seamlessly into a Java environment Can call Java methods, select Java fields, inherit Java classes, implement Java interfaces, etc. None of this requires glue code or interface descriptions Java code can also easily call into Scala code Scala code resembling Java is translated into virtually the same bytecodes.  Performance is usually on a par with Java
  • 8. Scala is a composition language New approach to module systems: component = class or trait composition via mixins Abstraction through parameters, abstract members (both types and values), self types gives dependency injection for free trait Analyzer { this : Backend => … } trait Backend extends Analyzer with Optimization with Generation { val global : Main import global ._ type OutputMedium <: Writable }
  • 9. Is Scala a “kitchen-sink language”? Not at all. In terms of feature count, Scala is roughly comparable to today’s Java and smaller than C# or C++. But Scala is deep , where other languages are broad . Two principles: 1. Focus on abstraction and composition, so that users can implement their own specialized features as needed. 2. Have the same sort of constructs work for very small as well as very large programs.
  • 10. Scala compared to Java Modeled in libraries: assert, enums, properties, events, actors, using, queries, … raw types + abstract types Scala removes Scala adds - wildcards + existential types enums + pattern matching - special treatment of interfaces + mixin composition with traits - break, continue + closures - primitive types + operator overloading - static members + a pure object system
  • 11. Scala cheat sheet (1): Definitions Scala method definitions: def fun(x: Int): Int = { result } def fun = result Scala variable definitions: var x: Int = expression val x: String = expression Java method definition: int fun( int x) { return result } (no parameterless methods) Java variable definitions: int x = expression final String x = expression
  • 12. Scala cheat sheet (2): Expressions Scala method calls: obj.meth(arg) 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, stmts: 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
  • 13. Scala cheat sheet (3): Objects and Classes Scala Class and Object class Sample(x: Int, val p: Int) { def instMeth(y: Int) = x + y } object Sample { def staticMeth(x: Int, y: Int) = x * y } Java Class with statics class Sample { private final int x; public final int p; Sample( int x, int p) { this.x = x; this.p = p; } int instMeth( int y) { return x + y; } static int staticMeth( int x, int y) { return x * y; } }
  • 14. Scala cheat sheet (4): Traits Scala Trait trait T { def abstractMth(x: String): Int def concreteMth(x: String) = x + field var field = “!” } Scala mixin composition: class C extends Super with T Java Interface interface T { int abstractMth(String x) } (no concrete methods) (no fields) Java extension + implementation: class C extends Super implements T
  • 15. Spring Cleaning Scala’s syntax is lightweight and concise. Due to: semicolon inference, type inference, lightweight classes, extensible API’s, closures as control abstractions. Average reduction in LOC: ≥ 2 due to concise syntax and better abstraction capabilities  Scala feels like a cleaned up Java … var capital = Map ( &quot;US&quot; -> &quot;Washington&quot; , &quot;Canada&quot; -> &quot;ottawa&quot; ) capital += ( &quot;Japan&quot; -> &quot;Tokyo&quot; ) for (c <- capital.keys) capital(c) = capital(c).capitalize assert(capital( &quot;Canada&quot; ) == &quot;Ottawa&quot; )
  • 16. … with one major difference It's x: Int instead of int x Why the change? Works better with type inference: var x = 0 instead of x = 0 // that's not a definition! Works better for large type expressions: val x: HashMap[String, (String, List[Char])] = … instead of public final HashMap<String, Pair<String, List<Char>>> x = …
  • 17. Scalability demands extensibility Take numeric data types Today's languages support int, long, float, double . Should they also support BigInt, BigDecimal, Complex, Rational, Interval, Polynomial ? There are good reasons for each of these types But a language combining them all would be too complex. Better alternative: Let users grow their language according to their needs.
  • 18. Adding new datatypes - seamlessly For instance type BigInt : def factorial ( x : BigInt ): BigInt = if ( x == 0) 1 else x * factorial ( x - 1) Compare with using Java's class: import java.math.BigInteger def factorial ( x : BigInteger ): BigInteger = if ( x == BigInteger.ZERO) BigInteger . ONE else x . multiply (factorial(x.subtract(BigInteger.ONE))) }
  • 19. Implementing new datatypes - seamlessly Here's how BigInt is implemented import java.math.BigInteger class BigInt ( val bigInteger : BigInteger ) extends java . lang . Number { def + ( that : BigInt ) = new BigInt ( this . bigInteger add that . bigInteger ) def - ( that : BigInt ) = new BigInt ( this . bigInteger subtract that . bigInteger ) … // other methods implemented analogously } + is an identifier; can be used as a method name Infix operations are method calls: a + b is the same as a.+(b) a add b is the same as a.add(b)
  • 20. Adding new control structures For instance using for resource control (proposed for Java 7) Instead of: using ( new BufferedReader ( new FileReader ( path ))) { f => println ( f . readLine ()) } val f = new BufferedReader ( new FileReader ( path )) try { println ( f . readLine ()) } finally { if ( f != null ) f . close () }
  • 21. Implementing new control structures: Here's how one would go about implementing using : def using [ T <: { def close () }] ( resource : T ) ( block : T => Unit ) { try { block ( resource ) } finally { if ( resource != null ) resource . close () } } T is a type parameter... … supporting a close method A closure that takes a T parameter
  • 22. Break and continue Scala does not have them. Why? They are a bit imperative; better use many smaller functions. Issues how to interact with closures. They are not needed! We can support them purely in the libraries. import scala.util.control.Breaks._ breakable { for (x <- elems) { println(x * 2) if (x > 0) break } }
  • 23. Getting back break and continue
  • 24. What makes Scala scalable? Many factors: strong typing, inference, little boilerplate,… But mainly, its tight integration of functional and object-oriented programming Functional programming: Makes it easy to build interesting things from simple parts, using higher-order functions, algebraic types and pattern matching, parametric polymorphism. Object-oriented programming: Makes it easy to adapt and extend complex systems, using subtyping and inheritance, dynamic configurations, classes as partial abstractions.
  • 25. Scala is object-oriented Every value is an object Every operation is a method call Exceptions to these rules in Java (such as primitive types, statics) are eliminated. scala> (1).hashCode res8: Int = 1 scala> (1).+(2) res10: Int = 3
  • 26. Scala is functional Scala is a functional language, in the sense that every function is a value. Functions can be anonymous, curried, nested. Many useful higher-order functions are implemented as methods of Scala classes. E.g: scala> val matrix = Array(Array(1, 0, 0), | Array(0, 1, 0), | Array(0, 0, 1)) matrix: Array[Array[Int]] = Array([I@164da25,… scala> matrix.exists(row => row.forall(0 ==)) res13: Boolean = false
  • 27. Functions are objects If functions are values, and values are objects, it follows that functions themselves are objects. The function type S => T is equivalent to scala.Function1[S, T], where Function1 is defined as follows: So functions are interpreted as objects with apply methods. For example, the anonymous successor function (x: Int ) => x + 1 is expanded to: trait Function1 [ -S , +T ] { def apply ( x : S ): T } new Function1 [ Int , Int ] { def apply ( x : Int ) = x + 1 }
  • 28. Why should I care? Since ( => ) is a class, it can be subclassed. So one can specialize the concept of a function. An obvious use is for arrays, which are mutable functions over integer ranges. A bit of syntactic sugaring lets one write: a(i) = a(i) + 2 for a.update(i, a.apply(i) + 2) class Array [ T ] ( l : Int ) extends ( Int => T ) { def length : Int = l def apply ( i : Int ): T = … def update ( i : Int , x : T ): Unit def elements : Iterator [ T ] def exists ( p : T => Boolean ) … }
  • 29. Partial functions Another useful abstraction are partial functions. These are functions that are defined only in some part of their domain. What's more, one can inquire with the isDefinedAt method whether a partial function is defined for a given value. Scala treats blocks of pattern matching cases as instances of partial functions. This lets one write control structures that are not easily expressible otherwise. trait PartialFunction [- A , + B ] extends ( A => B ) { def isDefinedAt ( x : A ): Boolean }
  • 30. Developing new paradigms Scala's flexibility makes it possible for users to grow the language into completely new paradigms. Case in point: concurrent programming Since Scala is interoperable, Java threads and concurrent libraries are available. But it's also possible to explore completely new paradigms.
  • 31. Erlang-style actors Two principal constructs (adopted from Erlang): Send ( ! ) is asynchronous; messages are buffered in an actor's mailbox. receive picks the first message in the mailbox which matches any of the patterns msgpat i . If no pattern matches, the actor suspends. // asynchronous message send actor ! message // message receive receive { case msgpat 1 => action 1 … case msgpat n => action n } A pattern matching block of type PartialFunction[ MessageType , ActionType ]
  • 32. A simple actor case class Data ( bytes : Array [ Byte ]) case class Sum ( receiver : Actor ) val checkSumCalculator = actor { var sum = 0 loop { receive { case Data ( bs ) => sum += hash ( bs ) case Sum ( receiver ) => receiver ! sum } } } } repeatedly receive messages Spawn a new actor
  • 33. Implementing receive Using partial functions, it is straightforward to implement receive: Here, self designates the currently executing actor, mailBox is its queue of pending messages, and extractFirst extracts first queue element matching given predicate. def receive [ T ] ( f : PartialFunction[Message , T ]): T = { self . mailBox . extractFirst ( f . isDefinedAt ) match { case Some(msg ) => f ( msg ) case None => self . wait ( messageSent ) }}
  • 34. Other Approaches to Scalability C++ Hard to scale down. Scaling up is possible for expert users. .NET Many languages with common interoperability. Hard to do something that's really different. Java Lingua franca makes it easy to understand other people's code. Not easy to scale down or up  pressure to add new languages.
  • 35. Where are we now? Scala Easy to scale down and up. Works well with a mix of expert users (for the framework) and non-experts (for the application code). Scala solves the expressiveness challenge for doing this. But does it also solve the safety issues? Problem: How to ensure that domain-specific code stays within its domain-specific library/language? For instance: How to ensure that a query formulated in Scala is non-recursive? Addressed by ongoing project: Pluggable type systems
  • 36. The Scala community 50000 downloads in 2008 300+ trak contributors 20+ messages/day on the mailing lists Industrial adoption has started, among others at: Twitter, Sony Pictures, Nature.com, Reaktor, Mimesis Republic, EDF Trading, … Scala LiftOff conference, May 2008. Scala talks in many conferences; next two at QCon, London, March 10-12.
  • 37. Tool support Standalone compiler: scalac Fast background compiler: fsc Interactive interpreter shell and script runner: scala Web framework: lift Testing frameworks: Specs, ScalaCheck, ScalaTest, SUnit, … IDE plugins for: Eclipse (supported by EDF) IntelliJ (supported by JetBrains) Netbeans (supported by Sun)
  • 38. Tool support Standalone compiler: scalac Fast background compiler: fsc Interactive interpreter shell and script runner: scala Web framework: lift Testing frameworks: Specs, ScalaCheck, ScalaTest, SUnit, … IDE plugins for: Eclipse (supported by EDF) IntelliJ (supported by JetBrains) Netbeans (supported by Sun)
  • 39. Who’s using it? Open source projects: lift wicket NetLogo SPDE: Scala branch for Processing Isabelle: GUI and code extractor Companies: Twitter: infrastructure Sony Pictures: middleware Nature.com: infrastructure SAP community: ESME company messaging Reaktor: many different projects Mimesis Republic: multiplayer games EDF: trading, …
  • 40. Learning Scala To get started: First steps in Scala, by Bill Venners published in Scalazine at www.artima.com Scala for Java Refugees by Daniel Spiewack (great blog series) To continue: Programming in Scala, by Odersky, Spoon, Venners, published by Artima,com Other books are in the pipeline.
  • 41. Thank You To try it out: scala-lang.org Thanks also to the (past and present) members of the Scala team: Philippe Altherr, Vincent Cremet, Iulian Dragos, Gilles Dubochet, Burak Emir, Sebastian Hack, Philipp Haller, Sean McDirmid, Ingo Meier, Adriaan Moors, Stéphane Micheloud, Nikolay Mihaylov, Anders Nielssen, Tiark Rompf, Lukas Rytz, Michel Schinz, Lex Spoon, Erik Stenman, Geoffrey Alan Washburn, Matthias Zenger .
  • 42. Relationship between Scala and other languages Main influences on the Scala design: Java, C# for their syntax, basic types, and class libraries, Smalltalk for its uniform object model, Eiffel for its uniform access principle, Beta for systematic nesting, ML, Haskell for many of the functional aspects. OCaml, OHaskel, PLT-Scheme, as other (less tightly integrated) combinations of FP and OOP. Pizza, Multi Java, Nice as other extensions of the Java platform with functional ideas. (Too many influences in details to list them all) Scala also seems to influence other new language designs, see for instance the closures and comprehensions in LINQ/C# 3.0.