Java. (for most of the purposes) The author thinks that if you are a smart Java developer and did not consider moving to Scala, you are wasting your life.
Java. (for most of the purposes) The author thinks that if you are a smart Java developer and did not consider moving to Scala, you are wasting your life. The presentation might look too opinionated even to a Scala developer.
Java. (for most of the purposes) The author thinks that if you are a smart Java developer and did not consider moving to Scala, you are wasting your life. The presentation might look too opinionated even to a Scala developer. No Harm Intended
object HelloWorld extends App { p r i n t l n ( ” Riga Dev Day” ) } More classical example: object HelloWorld { def main ( args : Array [ S t r i n g ] ) : Unit = { p r i n t l n ( ” Riga Dev Day” ) } }
infered here var name = ” Riga Dev Day” // compilation error here name = 5 // this is the same as var name : S t r i n g = ” Riga Dev Day” String interpolation: // compiler checks the name p r i n t l n ( s ” Hello , $name” ) // no SQL injection possible s q l ” s e l e c t ∗ from u s e r s where name = $name”
= new I n t e g e r (1) val y = new I n t e g e r (1) p r i n t l n ( x = = y ) // true case class User (name : String , surname : S t r i n g ) val user1 = new User ( ”John” , ”Smith” ) val user2 = new User ( ”John” , ”Smith” ) val user3 = new User ( ”John” , ” Notsmith ” ) p r i n t l n ( user1 = = user2 ) // true p r i n t l n ( user1 = = user3 ) // false
val la pto ps = countLaptops () val desktops = countDesktops () val t a b l e t s = countTablets () val phones = countPhones () val computers = for { l <− la pto ps d <− desktops t <− t a b l e t s p <− phones } y i e l d l ∗ 2 + d ∗ 3 − t + p ∗ l
CompletableFuture <In te ge r > l a p t o p s = countLaptops ( ) ; CompletableFuture <In te ge r > desktops = countDesktops ( ) ; CompletableFuture <In te ge r > t a b l e t s = countTablets ( ) ; CompletableFuture <In te ge r > phones = countPhones ( ) ; CompletableFuture <In te ge r > computers = l a p t o p s . thenCombine ( desktops , ( l , d ) −> l ∗ 2 + d ∗ 3) . thenCombine ( t a b l e t s , (sum , t ) −> sum − t ) . thenCombine ( phones , (sum , p ) −> sum + p ∗ ? ? ? ) ;
Play Web applications Slick LINQ like library Spark Cluster computing / big data Spray High performance HTTP and more Bonus track: Scala.js Compile Scala to JS (not GWT style)
May slow down the work of the whole team. Gets caught already during a probation period. Makes people swear his name for several months after he quits. Often betrays a profession and becomes a good developer.
the software development on a company level. May work for years without being decyphered. Ensures job security for himself and his colleagues up to the time when the company goes bankrupt.
code himself. Is so good that everyone considers him a good developer. Defines frameworks and approaches for the whole industries. Often becomes a technical lead of a huge multinational corporation.
<p r o j e c t xmlns=” h t t p : //maven . apache . org /POM/ 4 . 0 . 0 ” x m l n s : x s i=” h t t p : //www. w3 . org /2001/XMLSchema−i n s t a n c e ” x s i : s c h e m a L o c a t i o n=” h t t p : //maven . apache . org /POM/ 4 . 0 . 0 h t t p : //maven . apache . org / xsd /maven −4.0.0. xsd ”> <modelVersion>4 . 0 . 0</ modelVersion> <groupId>com . mycompany . app</ groupId> <a r t i f a c t I d>my−app</ a r t i f a c t I d> <v e r s i o n>1.0−SNAPSHOT </ v e r s i o n> <packaging>j a r</ packaging> <name>Maven Quick S t a r t Archetype</name> <u r l>h t t p : //maven . apache . org</ u r l> <dependencies> <dependency> <groupId>j u n i t</ groupId> <a r t i f a c t I d>j u n i t</ a r t i f a c t I d> <v e r s i o n>4 . 8 . 2</ v e r s i o n> <scope>t e s t</ scope> </ dependency> </ dependencies> </ p r o j e c t>
y v a l root = ( p r o j e c t i n f i l e ( ” . ” ) ) . s e t t i n g s ( name := ” h e l l o ” , v e r s i o n := ” 1.0 ” , s c a l a V e r s i o n := ” 2 . 1 1 . 7 ” ) More complex example. o r g a n i z a t i o n := ”com . mycompany . app” name := ”my−app” v e r s i o n := ”1.0−SNAPSHOT” dependencies + = ” j u n i t ” % ” j u n i t ” % ” 4 . 8 . 2 ” % ” t e s t ”
Account ( val money : I n t = 0) { def +(that : Account ) : Account = new Account ( t h i s . money + that . money ) } // old sbt versions like this feature a lot: :=, ˜=, <<=, + =, ++ =, <+ =, <++ = New versions still support these operators!
time. Scala Style Guide http://docs.scala-lang.org/style/ Effective Scala http://twitter.github.io/effectivescala/ Abuse this guide as it is tailored for Java develeopers: Databricks Scala Guide https://github.com/databricks/scala-style-guide
in Java, but more powerful. More support in a standard library: val option1 = map get key val option2 = l i s t . headOption val option3 = Try ( convert ) . toOption More powerful syntax: val option4 = for { value1 <− option1 value2 <− option2 value3 <− option3 } y i e l d myMethod( value1 , value2 , value3 ) It so good that Scala developers do not expect null to appear anywhere.
just like you would do it in Java. // plain assignment val notNull : S t r i n g = n u l l p r i n t l n ( notNull ) // null // my personal favorite: options with null val d e f i n e d : Option [ S t r i n g ] = Some( n u l l ) p r i n t l n ( d e f i n e d . i s D e f i n e d ) // true d e f i n e d map ( . length ) // NullPointerException Too easy to get caught by a simple grep of null over the files.
avoids the keyword. // default value for a field val p e r f e c t S c a l a : S t r i n g = p r i n t l n ( p e r f e c t S c a l a ) // null Too easy to notice after couple of times. Trivial to find with grep.
call from a legacy Java code def callFromJava ( notNull : S t r i n g ) : S t r i n g = notNull . trim // NullPointerException // somewhere else in Java callFromJava (map . get ( ”my. s e t t i n g ” )) Colleagues will fix to the following and fun is over. // call from a legacy Java code def callFromJava ( param : S t r i n g ) : Option [ S t r i n g ] = Option ( param ) map ( . trim ) // None // somewhere else in Java callFromJava (map . get ( ”my. s e t t i n g ” ))
initialization order object v a l u e s { val length = name . length val name = ” Riga Dev Day” } Not clever enough. // lazy initialization object v a l u e s { lazy val length = name . length lazy val name = ” Riga Dev Day” } (used in ”thin cake pattern”)
his own weapon. Becomes defensive. // only get called from Scala def c a l l 1 ( param : S t r i n g ) : Option [ S t r i n g ] = Option ( param map ( . trim )) // None // or even better def c a l l 2 ( param : Option [ S t r i n g ] ) : Option [ S t r i n g ] = Option ( param ) flatMap { param = > param map ( . trim ) // None } // awesome: returns Option[Option[String]] def c a l l 3 ( param : Option [ S t r i n g ] ) = Option ( param ) map { param = > param map ( . trim ) // None } Hard to battle if there is a Java code in a system.
a complex way, why to do it in some trivial way? // class with a dependency injection enabled c l a s s S e r v i c e ( r e p o s i t o r y : R e p o s i to ry ) { . . . } val s e r v i c e = new S e r v i c e ( r e p o s i t o r y ) val s e r v i c e = new S e r v i c e (mock [ Re p o s i to ry ] ) // modules! t r a i t Module { lazy val s e r v i c e : S e r v i c e = new S e r v i c e ( r e p o s i t o r y ) } object App extends Module // override the dependency object App extends Module { override lazy val s e r v i c e = new S e r v i c e 2 }
in Java. Spring Guice (dangerous! too lightweight) EJB3 dependency injection Easy to get laughed at by the experienced Scala developers. No easy way to hide.
of the good choices. http://www.warski.org/blog/2010/12/ di-in-scala-cake-pattern/ // Interface t r a i t UserInformationComponent { // What is needed to create the component def u s e r I n f o r m a t i o n ( u s e r : User ) t r a i t U s e r I n f o r m a t i o n { def userCountry : Country } } // Implementation t r a i t UserInformationComponentImpl extends UserInformationComponent { // Dependencies t h i s : CountryRepositoryComponent = > def u s e r I n f o r m a t i o n ( u s e r : User ) = new U s e r I n f o r m a t i o n I m p l ( u s e r ) c l a s s U s e r I n f o r m a t i o n I m p l ( v a l u s e r : User ) extends U s e r I n f o r m a t i o n { def userCountry : Country { // Using the dependency c o u n t r y R e p o s i t o r y . findByEmail ( u s e r . email ) } } }
of the good choices. http://www.warski.org/blog/2010/12/ di-in-scala-cake-pattern/ // Usage v a l env = new UserInformationComponentImpl with CountryRepositoryComponentImpl env . u s e r I n f o r m a t i o n ( User ( ” someuser@domain . p l ” ) ) . userCountry
// Define t r a i t Users { import s c a l a z . Reader def getUser ( i d : I n t ) = Reader (( u s e r R e p o s i t o r y : U s e r R e p o s i t o r y ) = > u s e r R e p o s i t o r y . get ( i d ) ) def f i n d U s e r ( username : S t r i n g ) = Reader (( u s e r R e p o s i t o r y : U s e r R e p o s i t o r y ) = > u s e r R e p o s i t o r y . f i n d ( username ) ) }
// Use object U s e r I n f o extends Users { def userEmail ( i d : I n t ) = { getUser ( i d ) map ( . email ) } def u s e r I n f o ( username : S t r i n g ) = f o r { u s e r < − f i n d U s e r ( username ) boss < − getUser ( u s e r . s u p e r v i s o r I d ) } y i e l d Map( ” fullName ” − > s ”${ u s e r . firstName} ${ u s e r . lastName}” , ” email ” − > s ”${ u s e r . email}” , ” boss ” − > s ”${boss . firstName} ${boss . lastName}” ) }
tests, or for reflection, for example. def f i x t u r e = new { val pi = 3 . 1 4 ; val e = 2.7 } value . asInstanceOf [{ def sum () } ] . sum () Unmaintainability experts jump on them when allowed. // awesome way to confuse people val p e r f e c t V a l u e = new { def value = 7 } // makes compilation slow def multipleReturnValues = { new { def x = 9; def y = 4 } } // uses reflection internally object MyObject {} object MyObject extends {}
to read and claim it improves thread safety. DSLs Invent your own programming language using Scala. Implicits Use Pimp My Library Pattern to do the actual programming. Scalaz Ensure the one does not live until the compilation is finished.
synchronized block in some sense. c l a s s Account { i n t money = 0; synchronized void c r e d i t ( i n t x ) { money + = x ; } synchronized void t r a n s f e r ( Account that , i n t x ) { money −= x ; that . c r e d i t ( x ) ; } } account1 . t r a n s f e r ( account2 , 5 ) ; account2 . t r a n s f e r ( account1 , 5 ) ;
Account extends Actor { var money = 0 def r e c e i v e = { case C r e d i t ( x ) = > money + = x case Transfer ( that , x ) = > money −= x that ! C r e d i t ( x ) } } account1 ! Transfer ( account2 , 5) account2 ! Transfer ( account1 , 5)
import U s e r R e p o s i t o r y . Command . c l a s s U s e r R e p o s i t o r y ( database : Database ) extends Actor { def r e c e i v e = { case Create ( u s e r ) = > sender ( ) ! database . save ( u s e r ) case Read ( i d ) = > sender ( ) ! database . load ( i d ) case Update ( u s e r ) = > sender ( ) ! database . save ( u s e r ) case Delete ( i d ) = > sender ( ) ! database . d e l e t e ( u s e r ) } } object U s e r R e p o s i t o r y { sealed t r a i t Command object Command { case c l a s s Create ( u s e r : User ) extends Command case c l a s s Read ( i d : S t r i n g ) extends Command case c l a s s Update ( u s e r : User ) extends Command case c l a s s Delete ( i d : s t r i n g ) extends Command } }
l a s s UserRepository ( database : Database ) { def c r e a t e ( user : User ) : S t r i n g = database . save ( user ) def read ( i d : S t r i n g ) : User = database . load ( i d ) def update ( user : User ) : Unit = database . save ( user ) def d e l e t e ( i d : S t r i n g ) : Unit = database . d e l e t e ( i d ) }
very easy to write your own DSL. v a l l i m i t = 10 v a l q1 = c o f f e e s f i l t e r ( . p r i c e < l i m i t ) map ( . name) v a l q2 = f o r ( c <− c o f f e e s ; i f c . p r i c e < l i m i t ) y i e l d c . name // SQL: select NAME from COFFEES where PRICE ¡ 10
very easy to write your own DSL. https://github.com/tpolecat/basic-dsl val b = new BASIC { 10 PRINT ”HELLO WORLD” 20 INPUT ”WHAT IS YOUR NAME?” AS N$ 30 INPUT ”HOW MANY TIMES SHALL I PRINT IT?” AS N 40 IF N <> INT(N) THEN 30 50 IF N < 1 THEN 30 60 PRINT ”OK THEN: ” 70 FOR I IN 1 TO N 80 PRINT N$ 90 NEXT I 95 PRINT ”BYE. ” }
classes. // play-json case c l a s s User ( name : String , surname : String , c r e a t e d : DateTime ) v a l u s e r = User ( ”John” , ”Smith” , DateTime . now) Json . toJson ( u s e r ) // internals def toJson [T] ( o : T) ( i m p l i c i t t j s : Writes [T ] ) : JsValue = t j s . w r i t e s ( o ) // syntactic sugar def toJson [T: Writes ] ( o : T) : JsValue def doStuff ( x : I n t )( i m p l i c i t val timeout : I n t ) i m p l i c i t val numbers = 7 doStuff (8)
trivial. The biggest problem and your worst enemy are the talented people atracted to it. If not prepared to face them, it might be better to focus on a different programming language.