5 Bullets to
Adoption	
  
	
  
Tomer	
  Gabel,	
  Wix	
  
May	
  2014	
  
WARMUP:	
  THE	
  BASICS	
  
This	
  is	
  Spar–	
  I	
  mean,	
  Java	
  
public class Person {!
private String name;!
private String surname;!
privat...
Let’s	
  make	
  some	
  people!	
  
public class SimplePersonGenerator {!
!
// Prepare a bunch of useful constants…!
!
pr...
IT’S	
  MADE	
  OF	
  PEOPLE!	
  
// Continued from previous slide!
!
private static Random random = new Random();!
!
publ...
Scala	
  syntax	
  101	
  
Java	
  
public class Person {!
private String name;!
private String surname;!
private int age;...
Scala	
  syntax	
  101	
  
Java	
  
public class Person {!
private String name;!
private String surname;!
private int age;...
Scala	
  syntax	
  101	
  
Java	
  
public class Person {!
private String name;!
private String surname;!
private int age;...
Onwards…	
  
Java	
  
public class SimplePersonGenerator {!
!
// Prepare a bunch of useful constants…!
!
private static Li...
Onwards…	
  
Java	
  
public class SimplePersonGenerator {!
!
// Prepare a bunch of useful constants…!
!
private static Li...
...	
  and	
  finally:	
  
Java	
  
private static Random random = new Random();!
!
public static Person generatePerson( in...
...	
  and	
  finally:	
  
Java	
  
private static Random random = new Random();!
!
public static Person generatePerson( in...
...	
  and	
  finally:	
  
Java	
  
private static Random random = new Random();!
!
public static Person generatePerson( in...
1.	
  TYPE	
  	
  
INFERENCE	
  
We	
  started	
  off	
  with:	
  
Java	
  
private static Random random = new Random();!
!
public static Person generatePer...
Let’s	
  simplify!	
  
Java	
  
private static Random random = new Random();!
!
public static Person generatePerson( int a...
Also	
  works	
  for	
  result	
  types:	
  
Java	
  
private static Random random = new Random();!
!
public static Person...
Also	
  works	
  for	
  result	
  types:	
  
Java	
  
private static Random random = new Random();!
!
public static Person...
Bonus	
  points:	
  Named	
  arguments	
  
Java	
  
private static Random random = new Random();!
!
public static Person g...
2.	
  THE	
  COLLECTION	
  FRAMEWORK	
  
Quick	
  example	
  
Java	
  
private static Random random = new Random();!
!
public static Person generatePerson( int age...
Quick	
  example	
  
Java	
  
private static Random random = new Random();!
!
public static Person generatePerson( int age...
Scala	
  collec[ons	
  primer	
  
// Some data to start with…!
val people = generatePeople( 5 )!
!
val names = people.map(...
Maps,	
  too	
  
val trivial: Map[ String, String ] =!
Map( "name" -> "Jeffrey Lebowsky",!
"alias" -> "The Dude" )!
!
val ...
And	
  much,	
  much,	
  much	
  more	
  
!
val ( adults, minors ) = people.partition( p => p.age >= 18 )!
!
val randomPai...
Caveat	
  emptor	
  
•  Scala	
  is	
  flexible	
  
–  You	
  can	
  do	
  the	
  same	
  thing	
  in	
  mul[ple	
  ways:	
...
3.	
  OPTIONS	
  
Back	
  in	
  Java-­‐Land	
  
public class Person {!
private String name;!
private String surname;!
private int age;!
!
pu...
Typical	
  solu[on	
  in	
  Java	
  
public class PartiallyKnownPerson {!
private String name;!
private String surname;!
p...
This	
  sucks	
  
public class PartiallyKnownPerson {!
private String name;!
private String surname;!
private Integer age;...
Falling	
  back	
  to	
  JavaDocs	
  
/**!
* Creates a new person.!
* @param name The person's name (or {@literal null} if...
Falling	
  back	
  to	
  JavaDocs	
  
/**!
* Creates a new person.!
* @param name The person's name (or {@literal null} if...
Falling	
  back	
  to	
  JavaDocs	
  
/**!
* Creates a new person.!
* @param name The person's name (or {@literal null} if...
Op[onal	
  arguments,	
  the	
  Scala	
  way	
  
case class PartiallyKnownPerson( name: Option[ String ] = None,!
surname:...
4.	
  TRAITS	
  
Back	
  in	
  Java	
  land…	
  
import org.slf4j.Logger;!
import org.slf4j.LoggerFactory;!
!
public class ClassWithLogs {!...
…	
  boilerplate	
  is	
  king	
  
import org.slf4j.Logger;!
import org.slf4j.LoggerFactory;!
!
public class ClassWithLogs...
What	
  can	
  we	
  do	
  about	
  it?	
  
•  A	
  solu[on	
  should:	
  
–  Require	
  minimal	
  boilerplate	
  
–  Cau...
Enter:	
  Scala	
  traits	
  
trait Logging {!
private val log = LoggerFactory.getLogger( this.getClass )!
!
protected def...
Boilerplate	
  is	
  king	
  
Java	
  
public class ClassWithLogs {!
private static Logger log =!
LoggerFactory.getLogger(...
Not	
  convinced?	
  
•  Consider:	
  
trait Iterator[ T ] {!
def hasNext: Boolean!
def next: T 	
 	
 // Or throw NoSuchEl...
A	
  saner	
  op[on	
  
trait BaseIterable[ T ] extends Iterable[ T ] {!
!
def firstOption = {!
val it = getIterator!
if (...
Massive	
  win!	
  
case class ArrayList[ T ]( array: Array[ T ] )!
extends BaseIterable[ T ] {!
!
def getIterator = new I...
5.	
  PATTERN	
  MATCHING	
  
Enhancing	
  our	
  domain	
  model	
  
Java	
  
enum MaritalStatus { !
single, married, divorced, widowed !
}!
!
enum Gen...
Enhancing	
  our	
  domain	
  model	
  
Java	
  
enum MaritalStatus { !
single, married, divorced, widowed !
}!
!
enum Gen...
Saluta[on	
  genera[on	
  
Java	
  
public String getSalutation() {!
if ( gender == null ) return null;!
switch( gender ) ...
Saluta[on	
  genera[on	
  
Java	
  
public String getSalutation() {!
if ( gender == null ) return null;!
switch( gender ) ...
Why	
  is	
  this	
  awesome?	
  
•  Other	
  use	
  cases	
  include:	
  
–  Reac[ng	
  to	
  objects	
  of	
  
unknown	
...
WE’RE	
  ALMOST
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption
Upcoming SlideShare
Loading in …5
×

5 Bullets to Scala Adoption

2,249 views

Published on

A talk given at the Wix Ukraine R&D meetup in Dnipropetrovsk, Ukraine on May 22, 2014.

So you've heard of this newfangled "Scala" thing and think it might be worth checking out. Good for you! Unfortunately, it's also daunting. Your first search for Scala is likely to pitch it as a "statically-typed hybrid object-oriented and functional language", which is technically true but doesn't really help much.

Instead, this talk will provide an overview of the language, focusing on five highly practical advantages Scala has over Java without a brain hemorrhage-inducing paradigm shift, followed by some tips and recommendations on Scala adoption in the real world and (as time allows) open-ended Q&A.

0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,249
On SlideShare
0
From Embeds
0
Number of Embeds
176
Actions
Shares
0
Downloads
40
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

5 Bullets to Scala Adoption

  1. 1. 5 Bullets to Adoption     Tomer  Gabel,  Wix   May  2014  
  2. 2. WARMUP:  THE  BASICS  
  3. 3. This  is  Spar–  I  mean,  Java   public class Person {! private String name;! private String surname;! private int age;! ! public Person( String name, String surname, int age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! public String getName() { return name; }! public String getSurname() { return surname; }! public int getAge() { return age; }! ! @Override! public String toString() { /* … */ }! }  
  4. 4. Let’s  make  some  people!   public class SimplePersonGenerator {! ! // Prepare a bunch of useful constants…! ! private static List<String> names;! private static List<String> surnames;! ! static {! names = new ArrayList<>();! names.add( "Jeffrey" );! names.add( "Walter" );! names.add( "Donald" );! ! surnames = new ArrayList<>();! surnames.add( "Lebowsky" );! surnames.add( "Sobchak" );! surnames.add( "Kerabatsos" );! }!
  5. 5. IT’S  MADE  OF  PEOPLE!   // Continued from previous slide! ! private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( random.nextInt( names.size() ) );! String surname = surnames.get( random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public List<Person> generatePeople( int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }!
  6. 6. Scala  syntax  101   Java   public class Person {! private String name;! private String surname;! private int age;! ! public Person( String name, String surname,! int age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! public String getName() { return name; }! public String getSurname() { return surname; }! public int getAge() { return age; }! ! @Override! public String toString() { /* … */ }! }    
  7. 7. Scala  syntax  101   Java   public class Person {! private String name;! private String surname;! private int age;! ! public Person( String name, String surname,! int age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! public String getName() { return name; }! public String getSurname() { return surname; }! public int getAge() { return age; }! ! @Override! public String toString() { /* … */ }! }     Scala   case class Person(! name: String,! surname: String,! age: Int )!    
  8. 8. Scala  syntax  101   Java   public class Person {! private String name;! private String surname;! private int age;! ! public Person( String name, String surname,! int age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! public String getName() { return name; }! public String getSurname() { return surname; }! public int getAge() { return age; }! ! @Override! public String toString() { /* … */ }! }     Scala   case class Person(! name: String,! surname: String,! age: Int )!   Provides:   –  Constructor   –  Property  geOers   –  hashCode/equals   –  toString   –  …  and  more    
  9. 9. Onwards…   Java   public class SimplePersonGenerator {! ! // Prepare a bunch of useful constants…! ! private static List<String> names;! private static List<String> surnames;! ! static {! names = new ArrayList<>();! names.add( "Jeffrey" );! names.add( "Walter" );! names.add( "Donald" );! ! surnames = new ArrayList<>();! surnames.add( "Lebowsky" );! surnames.add( "Sobchak" );! surnames.add( "Kerabatsos" );! }!
  10. 10. Onwards…   Java   public class SimplePersonGenerator {! ! // Prepare a bunch of useful constants…! ! private static List<String> names;! private static List<String> surnames;! ! static {! names = new ArrayList<>();! names.add( "Jeffrey" );! names.add( "Walter" );! names.add( "Donald" );! ! surnames = new ArrayList<>();! surnames.add( "Lebowsky" );! surnames.add( "Sobchak" );! surnames.add( "Kerabatsos" );! }! Scala   object NaiveScalaPersonGenerator {! ! private val names: List[ String ] =! List(! "Jeffrey",! "Walter",! "Donald" ! )! ! private val surnames: List[ String ] =! List(! "Lebowsky",! "Sobchak",! "Kerabatsos" ! )!
  11. 11. ...  and  finally:   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }!
  12. 12. ...  and  finally:   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random: Random = new Random! ! def generatePerson( age: Int ): Person = {! val name: String =! names( random.nextInt( names.size ) )! val surname: String =! surnames( random.nextInt( surnames.size ) )! new Person( name, surname, age )! }! ! !
  13. 13. ...  and  finally:   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random: Random = new Random! ! def generatePerson( age: Int ): Person = {! val name: String =! names( random.nextInt( names.size ) )! val surname: String =! surnames( random.nextInt( surnames.size ) )! new Person( name, surname, age )! }! ! def generatePeople( count: Int, age: Int ):! List[ Person ] = {! val people: mutable.ListBuffer[ Person ] =! mutable.ListBuffer.empty! for ( i <- 0 until count ) {! people.append( generatePerson( age ) )! }! people.result()! }! !
  14. 14. 1.  TYPE     INFERENCE  
  15. 15. We  started  off  with:   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public static List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random: Random = new Random! ! def generatePerson( age: Int ): Person = {! val name: String =! names( random.nextInt( names.size ) )! val surname: String =! surnames( random.nextInt( surnames.size ) )! new Person( name, surname, age )! }! ! def generatePeople( count: Int, age: Int ):! List[ Person ] = {! val people: mutable.ListBuffer[ Person ] =! mutable.ListBuffer.empty! for ( i <- 0 until count ) {! people.append( generatePerson( age ) )! }! people.result()! }! !
  16. 16. Let’s  simplify!   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public static List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random = new Random! ! def generatePerson( age: Int ): Person = {! val name =! names( random.nextInt( names.size ) )! val surname =! surnames( random.nextInt( surnames.size ) )! new Person( name, surname, age )! }! ! def generatePeople( count: Int, age: Int ):! List[ Person ] = {! val people =! mutable.ListBuffer.empty[ Person ]! for ( i <- 0 until count ) {! people.append( generatePerson( age ) )! }! people.result()! }! !
  17. 17. Also  works  for  result  types:   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public static List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random = new Random! ! def generatePerson( age: Int ) = {! val name =! names( random.nextInt( names.size ) )! val surname =! surnames( random.nextInt( surnames.size ) )! new Person( name, surname, age )! }! ! def generatePeople( count: Int, age: Int ) = {! val people =! mutable.ListBuffer.empty[ Person ]! for ( i <- 0 until count ) {! people.append( generatePerson( age ) )! }! people.result()! }! !
  18. 18. Also  works  for  result  types:   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random = new Random! ! def generatePerson( age: Int ) = {! val name =! names( random.nextInt( names.size ) )! val surname =! surnames( random.nextInt( surnames.size ) )! new Person( name, surname, age )! }! ! def generatePeople( count: Int, age: Int ) = {! val people =! mutable.ListBuffer.empty[ Person ]! for ( i <- 0 until count ) {! people.append( generatePerson( age ) )! }! people.result()! }! ! Not necessarily a good idea. • Code readability • Public APIs • Compilation times
  19. 19. Bonus  points:  Named  arguments   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public static List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random = new Random! ! def generatePerson( age: Int ) = Person(! name = names( random.nextInt( names.size ) )! surname =
 surnames( random.nextInt( surnames.size ) )! age = age! )! ! def generatePeople( count: Int, age: Int ) = {! val people =! mutable.ListBuffer.empty[ Person ]! for ( i <- 0 until count ) {! people.append( generatePerson( age ) )! }! people.result()! }! !
  20. 20. 2.  THE  COLLECTION  FRAMEWORK  
  21. 21. Quick  example   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public static List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random = new Random! ! def generatePerson( age: Int ) = Person(! name = names( random.nextInt( names.size ) )! surname =
 surnames( random.nextInt( surnames.size ) )! age = age! )! ! def generatePeople( count: Int, age: Int ) = {! val people =! mutable.ListBuffer.empty[ Person ]! for ( i <- 0 until count ) {! people.append( generatePerson( age ) )! }! people.result()! }! !
  22. 22. Quick  example   Java   private static Random random = new Random();! ! public static Person generatePerson( int age ) {! String name = names.get( ! random.nextInt( names.size() ) ); ! String surname = surnames.get( ! random.nextInt( surnames.size() ) );! return new Person( name, surname, age );! }! ! public static List<Person> generatePeople(! int count, int age ) {! List<Person> people = new ArrayList<>( count );! for ( int i = 0; i < count; i++ )! people.add( generatePerson( age ) );! return Collections.unmodifiableList( people );! }! Scala   private val random = new Random! ! def generatePerson( age: Int ) = Person(! name = names( random.nextInt( names.size ) )! surname =
 surnames( random.nextInt( surnames.size ) )! age = age! )! ! ! ! ! def generatePeople( count: Int, age: Int ) =! List.fill( count ) { generatePerson( age ) }!
  23. 23. Scala  collec[ons  primer   // Some data to start with…! val people = generatePeople( 5 )! ! val names = people.map( p => p.name )! ! val adults = people.filter( p => p.age >= 18 )! ! val averageAge = ! people.map( p => p.age ).sum / people.size! ! // Functions are 1st class citizens! def isAdult( p: Person ) = p.age >= 18! val adults2 = people.filter( isAdult )! assert( adults2 == adults )  
  24. 24. Maps,  too   val trivial: Map[ String, String ] =! Map( "name" -> "Jeffrey Lebowsky",! "alias" -> "The Dude" )! ! val directory: Map[ Char, List[ Person ] ] =! people! .groupBy( p => p.surname.head.toUpper )! .withDefaultValue( List.empty )! ! val beginningWithK: List[ Person ] =! directory( 'K' )! ! val countByFirstLetter: Map[ Char, Int ] = ! directory.mapValues( list => list.size )!  
  25. 25. And  much,  much,  much  more   ! val ( adults, minors ) = people.partition( p => p.age >= 18 )! ! val randomPairs = Random.shuffle( people ).grouped( 2 )! ! val youngest = people.minBy( p => p.age )! ! val oldest = people.maxBy( p => p.age )! ! val hasSeniorCitizens = people.exists( p => p.age >= 65 )  
  26. 26. Caveat  emptor   •  Scala  is  flexible   –  You  can  do  the  same  thing  in  mul[ple  ways:     people.foreach( person => println( person ) ) !// "Normal"! people.foreach { person => println( person ) } !// Block-style! people.foreach { println(_) } ! ! !// Placeholder syntax! people.foreach( println ) ! ! !// With function! people foreach println ! ! ! !// Infix notation   •  Stay  sane.  Stay  safe.   –  Pick  a  style  and  s[ck  with  it    
  27. 27. 3.  OPTIONS  
  28. 28. Back  in  Java-­‐Land   public class Person {! private String name;! private String surname;! private int age;! ! public Person( String name, String surname, int age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! public String getName() { return name; }! public String getSurname() { return surname; }! public int getAge() { return age; }! ! @Override! public String toString() { /* … */ }! }   We want to make these optional.
  29. 29. Typical  solu[on  in  Java   public class PartiallyKnownPerson {! private String name;! private String surname;! private Integer age;! ! public PartiallyKnownPerson( String name, String surname, Integer age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! public String getName() { return name; }! public String getSurname() { return surname; }! public Integer getAge() { return age; }! ! @Override! public String toString() { /* … */ }! }  
  30. 30. This  sucks   public class PartiallyKnownPerson {! private String name;! private String surname;! private Integer age;! ! public PartiallyKnownPerson ( String name, String surname, Integer age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! public String getName() { return name; }! public String getSurname() { return surname; }! public Integer getAge() { return age; }! ! @Override! public String toString() { /* … */ }! }   Returned values always need to be checked. Implicit; does not document intent.
  31. 31. Falling  back  to  JavaDocs   /**! * Creates a new person.! * @param name The person's name (or {@literal null} if unknown).! * @param surname The person's surname (or {@literal null} if unknown).! * @param age The person's age (or {@literal null} if unknown).! */! public PartiallyKnownPerson( String name, String surname, Integer age ) {! this.name = name;! this.surname = surname;! this.age = age;! }  
  32. 32. Falling  back  to  JavaDocs   /**! * Creates a new person.! * @param name The person's name (or {@literal null} if unknown).! * @param surname The person's surname (or {@literal null} if unknown).! * @param age The person's age (or {@literal null} if unknown).! */! public PartiallyKnownPerson( String name, String surname, Integer age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! This still sucks.
  33. 33. Falling  back  to  JavaDocs   /**! * Creates a new person.! * @param name The person's name (or {@literal null} if unknown).! * @param surname The person's surname (or {@literal null} if unknown).! * @param age The person's age (or {@literal null} if unknown).! */! public PartiallyKnownPerson( String name, String surname, Integer age ) {! this.name = name;! this.surname = surname;! this.age = age;! }! ! boolean isAdult( Person p ) {! return p.getAge() >= 18; // I love the smell of NPEs in the morning! }   This still sucks.Because:
  34. 34. Op[onal  arguments,  the  Scala  way   case class PartiallyKnownPerson( name: Option[ String ] = None,! surname: Option[ String ] = None,! age: Option[ Int ] = None ) {! ! def isAdult = age.map( _ > 18 )! }! ! val person = PartiallyKnownPerson( name = Some( "Brandt" ) )! ! val explicitAccess = person.age.get // <-- NoSuchElementException thrown here! ! val withDefault = person.name.getOrElse( "Anonymous" )! println( "Hello " + withDefault + "!" )! ! // Options are also zero- or single-element collections!! def greet( whom: Iterable[ String ] ) =! whom.foreach { name => println( "hello" + name ) }! greet( person.name )  
  35. 35. 4.  TRAITS  
  36. 36. Back  in  Java  land…   import org.slf4j.Logger;! import org.slf4j.LoggerFactory;! ! public class ClassWithLogs {! private static Logger log = LoggerFactory.getLogger( ClassWithLogs.class );! ! public String getNormalizedName( Person person ) {! log.info( "getNormalizedName called" );! log.debug( "Normalizing " + person.toString() );! String normalizedName = person.getName().toUpperCase().trim();! log.debug( "Normalized name is: " + normalizedName );! return normalizedName;! }! }  
  37. 37. …  boilerplate  is  king   import org.slf4j.Logger;! import org.slf4j.LoggerFactory;! ! public class ClassWithLogs {! private static Logger log = LoggerFactory.getLogger( ClassWithLogs.class );! ! public String getNormalizedName( Person person ) {! log.info( "getNormalizedName called" );! log.debug( "Normalizing " + person.toString() );! String normalizedName = person.getName().toUpperCase().trim();! log.debug( "Normalized name is: " + normalizedName );! return normalizedName;! }! }   x1000 classes… Eager evaluation
  38. 38. What  can  we  do  about  it?   •  A  solu[on  should:   –  Require  minimal  boilerplate   –  Cause  few  or  no  side-­‐effects   –  Be  composable   –  Perform  well   •  An  abstract  base  class  is   useless   –  Only  one  base  class  allowed   –  No  way  to  do  lazy  evalua[on  
  39. 39. Enter:  Scala  traits   trait Logging {! private val log = LoggerFactory.getLogger( this.getClass )! ! protected def logInfo( message: => String ) = ! if ( log.isInfoEnabled ) log.info ( message )! ! protected def logDebug( message: => String ) = ! if ( log.isDebugEnabled ) log.debug( message )! ! protected def logWarn( message: => String ) = ! if ( log.isWarnEnabled ) log.warn ( message )! ! protected def logError( message: => String ) = ! if ( log.isErrorEnabled ) log.error( message )! }! !
  40. 40. Boilerplate  is  king   Java   public class ClassWithLogs {! private static Logger log =! LoggerFactory.getLogger(! ClassWithLogs.class );! ! public String getNormalizedName(! Person person ) {! log.info( "getNormalizedName called" );! log.debug( "Normalizing " +! person.toString() );! String normalizedName =! person.getName().toUpperCase().trim();! log.debug( "Normalized name is: " +! normalizedName );! return normalizedName;! }! }   Scala   ! class ClassWithLogs extends Logging {! ! ! ! def getNormalizedName( person: Person ) = {! logInfo( "getNormalizedName called" )! logDebug( "Normalizing " +! person.toString )! val normalizedName =! person.name.toUpperCase.trim! logDebug( "Normalized name is: " +! normalizedName )! normalizedName! }! }  
  41. 41. Not  convinced?   •  Consider:   trait Iterator[ T ] {! def hasNext: Boolean! def next: T // Or throw NoSuchElementException! }! ! trait Iterable[ T ] {! def getIterator: Iterator[ T ]! def first: T // Or throw NoSuchElementException! def firstOption: Option[ T ]! def last: T // Or throw NoSuchElementException! def lastOption: Option[ T ]! def size: Int! }     •  What  if  you  need  to  implement  ArrayList,  HashSet,  LinkedList…?  
  42. 42. A  saner  op[on   trait BaseIterable[ T ] extends Iterable[ T ] {! ! def firstOption = {! val it = getIterator! if ( it.hasNext ) Some( it.next ) else None! }! ! def first = firstOption.getOrElse( throw new NoSuchElementException )! ! def size = {! val it = getIterator! var count = 0! while ( it.hasNext ) { count += 1; it.next }! count! }! ! // …! }  
  43. 43. Massive  win!   case class ArrayList[ T ]( array: Array[ T ] )! extends BaseIterable[ T ] {! ! def getIterator = new Iterator[ T ] {! var index = 0! ! def hasNext = index < array.length! ! def next =! if ( hasNext ) {! val value = array( index )! index += 1! value! } else! throw new NoSuchElementException! }! }   •  No  boilerplate   •  Implement  only  “missing  bits”   •  Mix  and  match  mul[ple  traits!   •  Need  features?   –  Add  to  your  concrete  class   •  Need  performance?   –  Override  the  default   implementa[on  
  44. 44. 5.  PATTERN  MATCHING  
  45. 45. Enhancing  our  domain  model   Java   enum MaritalStatus { ! single, married, divorced, widowed ! }! ! enum Gender { ! male, female ! }! ! class Person {! private String name;! private String surname;! private int age;! private MaritalStatus maritalStatus;! private Gender gender;! // …! }!
  46. 46. Enhancing  our  domain  model   Java   enum MaritalStatus { ! single, married, divorced, widowed ! }! ! enum Gender { ! male, female ! }! ! class Person {! private String name;! private String surname;! private int age;! private MaritalStatus maritalStatus;! private Gender gender;! // …! }! Scala   sealed trait MaritalStatus! case object Single extends MaritalStatus! case object Married extends MaritalStatus! case object Divorced extends MaritalStatus! case object Widowed extends MaritalStatus! ! sealed trait Gender! case object Male extends Gender! case object Female extends Gender! ! case class Person(! name: String, surname: String, age: Int,! maritalStatus: Option[ MaritalStatus ],! gender: Option[ Gender ] )!  
  47. 47. Saluta[on  genera[on   Java   public String getSalutation() {! if ( gender == null ) return null;! switch( gender ) {! case male:! return "Mr.";! ! case female:! if ( maritalStatus == null )! return "Ms.";! switch( maritalStatus ) {! case single:! return "Miss";! ! case married:! case divorced:! case widowed:! return "Mrs.";! }! }!
  48. 48. Saluta[on  genera[on   Java   public String getSalutation() {! if ( gender == null ) return null;! switch( gender ) {! case male:! return "Mr.";! ! case female:! if ( maritalStatus == null )! return "Ms.";! switch( maritalStatus ) {! case single:! return "Miss";! ! case married:! case divorced:! case widowed:! return "Mrs.";! }! }! Scala   ! ! def salutation: Option[ String ] = ! ( gender, maritalStatus ) match {! case (Some(Male ), _ ) => Some("Mr.")! case (Some(Female), Some(Single)) => Some("Miss")! case (Some(Female), None ) => Some("Ms.")! case (Some(Female), _ ) => Some("Mrs.")! case (None , _ ) => None! }  
  49. 49. Why  is  this  awesome?   •  Other  use  cases  include:   –  Reac[ng  to  objects  of   unknown  type   –  Decomposing  structures   •  Extensible  via  extractor   objects   •  Compiler  performs   exhaus0veness  check!  
  50. 50. WE’RE  ALMOST

×