SlideShare ist ein Scribd-Unternehmen logo
1 von 108
Downloaden Sie, um offline zu lesen
Pragmatic
Real-World Scala

             Jonas Bonér
       Scalable Solutions
“If I were to pick a language
to use today other than Java,
it would be Scala”
                 James Gosling
Chat app in Lift
    Build a multi-user, comet-based chat app




    About 30 lines of code




    Three slides worth




    Slides By David Pollak, creator of Lift

Define Messages
case class Add(who: Actor)
case class Remove(who: Actor)
case class Messages(msgs: List[String])
Chat Server
object ChatServer extends Actor {
  private var listeners: List[Actor] = Nil
  private var msgs: List[String] = Nil
  def act = loop {
    react {
      case s: String =>
        msgs = s :: msgs
        listeners.foreach(l => l ! Messages(msgs))
      case Add(who) =>
        listeners = who :: listeners
        who ! Messages(msgs)
      case Remove(who) => listeners -= who
    }
  }
  this.start
}
Chat Comet Component
class Chat extends CometActor {
  private var msgs: List[String] = Nil
  def render =
    <div>
      <ul>{ msgs.reverse.map(m => <li>{ m }</li>) }</ul>
      { ajaxText(quot;quot;, s => { ChatServer ! s; Noop }) }
    </div>
  override def localSetup = ChatServer ! Add(this)
  override def localShutdown = ChatServer ! Remove(this)
  override def lowPriority = {
    case Messages(m) => msgs = m; reRender(false)
  }
}
Demo
Scalable language
Unique and elegant blend of



OO FP           +
2003
                            Since
              Pragmatic
                 Sponsored by EPFL
Martin Odersky
      Seamless Java interoperability
Friendly and supportive      Production
community                    ready

                          Statically typed
              JVM
Runs on the
Unique and elegant blend of



       is...
Expressive &
       light-weight
val phonebook = Map(
  “Jonas” -> “123456”,
  “Sara” -> “654321”)
phonebook += (“Jacob” -> “987654”)
println(phonebook(“Jonas”))
High-level
            Java version
boolean hasUpperCase = false;
for (int i = 0; i < name.length(); i++) {
  if (Character.isUpperCase(name.charAt(i)))
  {
    hasUpperCase = true;
    break;
  }
}
High-level
             Scala version

val hasUpperCase = name.exists(_.isUpperCase)
Concise
// Java
public class Person {
 private String name;
 private int age;
 public Person(String name,
                int age) {
   this.name = name;
                                      // Scala
   this.age = age;
 }
                                      class Person(
 public String getName() {
                                        var name: String,
   return name;
 }
                                        var age: Int)
 public int getAge() {
   return age;
 }
 public void setName(String name) {
   this.name = name;
 }
 public void setAge(age: int) {
   this.age = age;
 }
}
Pure OO
1+2
1.+(2)

123.toString()
Extensible
val service = actor {
  loop {
    receive {
      case Add(x,y) => reply(x+y)
      case Sub(x,y) => reply(x-y)
    }
  }
}
                      6
service ! Add(4, 2)
Pragmatic
def users =
  <users>
    <user role=”customer”>
      <name>{ user.name }</name>
      <password>{ user.password }</password>
      <email>{ user.email }</email>
    </user>
    ...
  </users>
Pragmatic
users match {
  case <users>{users @ _*}</users> =>
    for (user <- users)
      println(“User “ + (user  “name”).text)
}
Great for DSLs
     Apache Camel
“direct:a“ ==> {
  loadbalance roundrobin {
    to (“mock:a“)
    to (“mock:b“)
    to (“mock:c“)
  }
}
deep
 Scala is
But you don’t need to go very deep
to still have fun and be productive
Java
Tastier Java
Different beast
Composition
Composition

     large
in
2
building blocks
Traits
       &
   &


  Self-type
annotations
Trait
trait Dad {
  private var children: List[Child] = Nil

    def addChild(child: Child) =
      children = child :: children

    def getChildren = children.clone
}
Base

class Man(val name: String) extends Human
Plumbing
Static mixin composition

class Man(val name: String) extends Human with Dad
Static mixin composition
          usage
class Man(val name: String) extends Human with Dad


val jonas = new Man(“Jonas”)
jonas.addChild(new Child(“Jacob”))
Dynamic mixin composition


val jonas = new Man(“Jonas”) with Dad
Dynamic mixin composition
         usage
val jonas = new Man(“Jonas”) with Dad


jonas.addChild(new Child(“Jacob”))
3   different type of traits
1
Rich interface
trait RichIterable[A] {
  def iterator: Iterator[A] // contract method

    def foreach(f: A => Unit) = {
      val iter = iterator
      while (iter.hasNext) f(iter.next)
    }

    def foldLeft[B](seed: B)(f: (B, A) => B) = {
       var result = seed
       foreach(e => result = f(result, e))
       result
     }
}
Rich interface
val richSet =
    new java.util.HashSet[Int]
    with RichIterable[Int]

richSet.add(1)
richSet.add(2)

richSet.foldLeft(0)((x, y) => x + y)
   3
2
Stackable modifications
trait IgnoreCaseSet
  extends java.util.Set[String] {

    abstract override def add(e: String) = {
      super.add(e.toLowerCase)
    }
    abstract override def contains(e: String) = {
      super.contains(e.toLowerCase)
    }
    abstract override def remove(e: String) = {
      super.remove(e.toLowerCase)
    }
}
Stackable modifications
val set =
    new java.util.HashSet[String]
    with IgnoreCaseSet

set.add(“HI THERE“)      // uppercase

set.contains(“hi there“) // lowercase
     true
Add another trait interceptor
trait LoggableSet
  extends java.util.Set[String] {

    abstract override def add(e: String) = {
      println(“Add :“ + e)
      super.add(e)
    }

    abstract override def remove(e: String) = {
      println(“Remove :“ + e)
      super.remove(e)
    }
}
Run the stack of interceptors
  val set =
    new java.util.HashSet[String]
    with IgnoreCaseSet
    with LoggableSet

  set.add(“HI THERE“)
     “Add: HI THERE”


      Prints in uppercase
Change the order
val set =
  new java.util.HashSet[String]
  with LoggableSet
  with IgnoreCaseSet

set.add(“HI THERE“)
   “Add: hi there”


     Prints in lowercase
3
Multiple views
    Trait                   Trait




Trait                         Trait
             Base




                    Trait
Multiple views
    Trait                   Trait




Trait                         Trait
             Base




                    Trait
Traits
 Multiple
personalities
Traits


          Multiple
         facets
Base
class Order(val cust: Customer)
Facets
trait   Entity { ... }
trait   InventoryItemSet { ... }
trait   Invoicable { ... }
trait   PurchaseLimiter { ... }
trait   MailNotifier { ... }
trait   ACL { ... }
trait   Versioned { ... }
trait   Transactional { ... }
Composition
val order = new Order(customer)
    with Entity
    with InventoryItemSet
    with Invoicable
    with PurchaseLimiter
    with MailNotifier
    with ACL
    with Versioned
    with Transactional
What do you
  need?
DI
this: <deps> =>
this: <deps> =>
Dependency declaration
trait UserService {
  this: UserRepository =>
  ...
  // provided with composition
  userRepository.merge(user)
}

…using self-type annotation
Duck typing
walks like a duck…
   if it

   and talks like a duck…

   then it’s a duck

Duck typing
Structural Typing:
      Duck-typing done right
def authorize(target: { def getACL: ACL }) = {

    val acl = target.getACL
    ... //authorize
}



          Statically enforced
Composition

   in small
“It's Time to Get Good at
 Functional Programming”
                   Dr Dobb’s Journal
                Issue December 2008
What’s
all the

buzz
about?
Deterministic
               Reusable
High-level

        FP      Referentially
                transparent

Immutable    Declarative
    Orthogonal
Lego
FP is like
Small reusable pieces

       input
with



       output
and
Unix pipes

cat File | grep 'println' | wc
Functions

(x: Int) => x + 1
Functions as values
  val inc = (x: Int) => x + 1


  inc(1)   2
Functions as parameters
         high-order
List(1, 2, 3).map((x: Int) => x + 1)

    List(2, 3, 4)
Functions as parameters
          with sugar
List(1, 2, 3).map((x: Int) => x + 1)


List(1, 2, 3).map(x => x + 1)


List(1, 2, 3).map(_ + 1)
Functions as closures

val addMore = (x: Int) => x + more
more?
What is
Some value outside
the function’s lexical scope
 var more = 7
 val addMore = (x: Int) => x + more


 addMore(3)  10
 more = 8
 addMore(3)  11
Functional
Data Structures
Immutable
The almighty




List
Lists
Grow at the front
Insert at front  O(1)
Insert at end  O(n)
List creation
  List(1, 2, 3)


1 :: 2 :: 3 :: Nil
Basics
val list = List(1, 2, 3)
list.head    1
list.tail     List(2, 3)
list.isEmpty  false
High-level operations
val list = List(1, 2, 3)
list.map(_ + 1)      List(2,   3, 4)
list.filter(_ < 2)  List(3)
list.exists(_ == 3)  true
list.drop(2)         List(3)
list.reverse         List(3,   2, 1)
list.sort(_ > _)     List(3,   2, 1)
List.flatten(list)  List(1,    2, 3)
list.slice(2, 3)     List(3)
...
115
                       List
functions defined on
Tuples
def getNameAndAge: Tuple2[String, Int] = {
  val name = ...
  val age = ...
  (name, age)
}


val (name, age) = getNameAndAge
println(“Name: “ + name)
println(“Age: “ + age)
Other
functional data structures:
                   Maps
                    Sets
                  Trees
                  Stacks
For comprehensions

  for (n <- names)
    println(n)
Like SQL queries
for {
  att <- attendees
  if att.name == “Fred”
  lang <- att.spokenLanguages
  if lang == “Danish”
} println(att)

Find all attendees named Fred that speaks Danish
for / yield
val companiesForAttendeesFromLondon =
  for {
    att <- attendees
    if att.address.city == “London”
  } yield att.company
Everything returns a value


    for (thing <- thingsFromHere)
    yield getRealThing(thing)
Everything returns a value


   val things =
     for (thing <- thingsFromHere)
     yield getRealThing(thing)
Everything returns a value


   if (fromHere) {
     for (thing <- thingsFromHere)
     yield getRealThing(thing)
   } else {
     for (thing <- thingsFromThere)
     yield thing
   }
Everything returns a value

 val things =
   if (fromHere) {
     for (thing <- thingsFromHere)
     yield getRealThing(thing)
   } else {
     for (thing <- thingsFromThere)
     yield thing
   }
Everything returns a value

  try {
    if (fromHere) {
      for (thing <- thingsFromHere)
      yield getRealThing(thing)
    } else {
      for (thing <- thingsFromThere)
      yield thing
    }
  } catch {
    case e => error(e); Nil
  }
Everything returns a value
val things =
  try {
    if (fromHere) {
      for (thing <- thingsFromHere)
      yield getRealThing(thing)
    } else {
      for (thing <- thingsFromThere)
      yield thing
    }
  } catch {
    case e => error(e); Nil
  }
Everything returns a value
def getThingsFromSomewhere(
  fromHere: Boolean): List[Thing] = {
  try {
    if (fromHere) {
      for (thing <- thingsFromHere)
      yield getRealThing(thing)
    } else {
      for (thing <- thingsFromThere)
      yield thing
    }
  } catch {
    case e => error(e); Nil
  }
}
Pattern
matching
Pattern matching
def matchAny(a: Any): Any = a match {
  case 1                => “one”
  case “two”            => 2
  case i: Int           => “scala.Int”
  case <tag>{ t }</tag> => t
  case head :: tail     => head
  case _                => “default”
}
Tools
Tools: scala/bin
            scala
           scalac
               fsc
        scaladoc
             sbaz
Tools: IDEs
        Eclipse
    NetBeans
 IntelliJ IDEA
         Emacs
           JEdit
Building
             Maven
               Ant
SBT (Simple Build Tool )
Tools: Testing
          Specs
    ScalaCheck
      ScalaTest
          SUnit
Frameworks: Web
            Lift
           Sweet
           Slinky
            Pinky
Learn more
jonas@jonasboner.com
  http://jonasboner.com
     http://scala-lang.org
Professional help
Consulting Training Mentoring

    http://scalablesolutions.se
Pragmatic
Real-World Scala

              Jonas Bonér
       Scalable Solutions


        Copyright 2009 Scalable Solutions

Weitere ähnliche Inhalte

Was ist angesagt?

Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of AbstractionAlex Miller
 
The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPathsVincent Pradeilles
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickHermann Hueck
 
Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactOdessaJS Conf
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Compact and safely: static DSL on Kotlin
Compact and safely: static DSL on KotlinCompact and safely: static DSL on Kotlin
Compact and safely: static DSL on KotlinDmitry Pranchuk
 
LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기Wanbok Choi
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional ProgrammingDmitry Buzdin
 
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin WayTDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Waytdc-globalcode
 
Madrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovyMadrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovyIván López Martín
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 

Was ist angesagt? (19)

Scala vs Ruby
Scala vs RubyScala vs Ruby
Scala vs Ruby
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of Abstraction
 
The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPaths
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with Slick
 
Scala vs java 8
Scala vs java 8Scala vs java 8
Scala vs java 8
 
Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReact
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Into Clojure
Into ClojureInto Clojure
Into Clojure
 
Compact and safely: static DSL on Kotlin
Compact and safely: static DSL on KotlinCompact and safely: static DSL on Kotlin
Compact and safely: static DSL on Kotlin
 
LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional Programming
 
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin WayTDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
 
Madrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovyMadrid gug - sacando partido a las transformaciones ast de groovy
Madrid gug - sacando partido a las transformaciones ast de groovy
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Polyglot JVM
Polyglot JVMPolyglot JVM
Polyglot JVM
 
core.logic introduction
core.logic introductioncore.logic introduction
core.logic introduction
 
Grammarware Memes
Grammarware MemesGrammarware Memes
Grammarware Memes
 

Andere mochten auch

Health Db Primer
Health Db PrimerHealth Db Primer
Health Db Primerparag978978
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?Vasil Remeniuk
 
Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayYardena Meymann
 
HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012
HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012
HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012Matt Raible
 
Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008Yardena Meymann
 

Andere mochten auch (8)

Health Db Primer
Health Db PrimerHealth Db Primer
Health Db Primer
 
Enterprise Osgi
Enterprise OsgiEnterprise Osgi
Enterprise Osgi
 
Scale up your thinking
Scale up your thinkingScale up your thinking
Scale up your thinking
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
All about scala
All about scalaAll about scala
All about scala
 
Concurrency in Scala - the Akka way
Concurrency in Scala - the Akka wayConcurrency in Scala - the Akka way
Concurrency in Scala - the Akka way
 
HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012
HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012
HTML5 with Play Scala, CoffeeScript and Jade - UberConf 2012
 
Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008Scala at HUJI PL Seminar 2008
Scala at HUJI PL Seminar 2008
 

Ähnlich wie Scala Chat App in 30 Lines of Code

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
JBUG 11 - Scala For Java Programmers
JBUG 11 - Scala For Java ProgrammersJBUG 11 - Scala For Java Programmers
JBUG 11 - Scala For Java ProgrammersTikal Knowledge
 
Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....Raffi Krikorian
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVMVaclav Pech
 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009David Pollak
 
여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala LanguageAshal aka JOKER
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghStuart Roebuck
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Jesper Kamstrup Linnet
 

Ähnlich wie Scala Chat App in 30 Lines of Code (20)

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
JBUG 11 - Scala For Java Programmers
JBUG 11 - Scala For Java ProgrammersJBUG 11 - Scala For Java Programmers
JBUG 11 - Scala For Java Programmers
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....Scala + WattzOn, sitting in a tree....
Scala + WattzOn, sitting in a tree....
 
Concurrency on the JVM
Concurrency on the JVMConcurrency on the JVM
Concurrency on the JVM
 
Beginning Scala Svcc 2009
Beginning Scala Svcc 2009Beginning Scala Svcc 2009
Beginning Scala Svcc 2009
 
여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
A bit about Scala
A bit about ScalaA bit about Scala
A bit about Scala
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
Scala en
Scala enScala en
Scala en
 
Scala
ScalaScala
Scala
 

Scala Chat App in 30 Lines of Code

  • 1. Pragmatic Real-World Scala Jonas Bonér Scalable Solutions
  • 2. “If I were to pick a language to use today other than Java, it would be Scala” James Gosling
  • 3. Chat app in Lift Build a multi-user, comet-based chat app  About 30 lines of code  Three slides worth  Slides By David Pollak, creator of Lift 
  • 4. Define Messages case class Add(who: Actor) case class Remove(who: Actor) case class Messages(msgs: List[String])
  • 5. Chat Server object ChatServer extends Actor { private var listeners: List[Actor] = Nil private var msgs: List[String] = Nil def act = loop { react { case s: String => msgs = s :: msgs listeners.foreach(l => l ! Messages(msgs)) case Add(who) => listeners = who :: listeners who ! Messages(msgs) case Remove(who) => listeners -= who } } this.start }
  • 6. Chat Comet Component class Chat extends CometActor { private var msgs: List[String] = Nil def render = <div> <ul>{ msgs.reverse.map(m => <li>{ m }</li>) }</ul> { ajaxText(quot;quot;, s => { ChatServer ! s; Noop }) } </div> override def localSetup = ChatServer ! Add(this) override def localShutdown = ChatServer ! Remove(this) override def lowPriority = { case Messages(m) => msgs = m; reRender(false) } }
  • 9. Unique and elegant blend of OO FP +
  • 10. 2003 Since Pragmatic Sponsored by EPFL Martin Odersky Seamless Java interoperability Friendly and supportive Production community ready Statically typed JVM Runs on the
  • 11. Unique and elegant blend of is...
  • 12. Expressive & light-weight val phonebook = Map( “Jonas” -> “123456”, “Sara” -> “654321”) phonebook += (“Jacob” -> “987654”) println(phonebook(“Jonas”))
  • 13. High-level Java version boolean hasUpperCase = false; for (int i = 0; i < name.length(); i++) { if (Character.isUpperCase(name.charAt(i))) { hasUpperCase = true; break; } }
  • 14. High-level Scala version val hasUpperCase = name.exists(_.isUpperCase)
  • 15. Concise // Java public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; // Scala this.age = age; } class Person( public String getName() { var name: String, return name; } var age: Int) public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(age: int) { this.age = age; } }
  • 17. Extensible val service = actor { loop { receive { case Add(x,y) => reply(x+y) case Sub(x,y) => reply(x-y) } } } 6 service ! Add(4, 2)
  • 18. Pragmatic def users = <users> <user role=”customer”> <name>{ user.name }</name> <password>{ user.password }</password> <email>{ user.email }</email> </user> ... </users>
  • 19. Pragmatic users match { case <users>{users @ _*}</users> => for (user <- users) println(“User “ + (user “name”).text) }
  • 20. Great for DSLs Apache Camel “direct:a“ ==> { loadbalance roundrobin { to (“mock:a“) to (“mock:b“) to (“mock:c“) } }
  • 22. But you don’t need to go very deep to still have fun and be productive
  • 23. Java
  • 27. Composition large in
  • 29. Traits & & Self-type annotations
  • 30. Trait trait Dad { private var children: List[Child] = Nil def addChild(child: Child) = children = child :: children def getChildren = children.clone }
  • 31. Base class Man(val name: String) extends Human
  • 33. Static mixin composition class Man(val name: String) extends Human with Dad
  • 34. Static mixin composition usage class Man(val name: String) extends Human with Dad val jonas = new Man(“Jonas”) jonas.addChild(new Child(“Jacob”))
  • 35. Dynamic mixin composition val jonas = new Man(“Jonas”) with Dad
  • 36. Dynamic mixin composition usage val jonas = new Man(“Jonas”) with Dad jonas.addChild(new Child(“Jacob”))
  • 37. 3 different type of traits
  • 38. 1
  • 39. Rich interface trait RichIterable[A] { def iterator: Iterator[A] // contract method def foreach(f: A => Unit) = { val iter = iterator while (iter.hasNext) f(iter.next) } def foldLeft[B](seed: B)(f: (B, A) => B) = { var result = seed foreach(e => result = f(result, e)) result } }
  • 40. Rich interface val richSet = new java.util.HashSet[Int] with RichIterable[Int] richSet.add(1) richSet.add(2) richSet.foldLeft(0)((x, y) => x + y) 3
  • 41. 2
  • 42. Stackable modifications trait IgnoreCaseSet extends java.util.Set[String] { abstract override def add(e: String) = { super.add(e.toLowerCase) } abstract override def contains(e: String) = { super.contains(e.toLowerCase) } abstract override def remove(e: String) = { super.remove(e.toLowerCase) } }
  • 43. Stackable modifications val set = new java.util.HashSet[String] with IgnoreCaseSet set.add(“HI THERE“) // uppercase set.contains(“hi there“) // lowercase  true
  • 44. Add another trait interceptor trait LoggableSet extends java.util.Set[String] { abstract override def add(e: String) = { println(“Add :“ + e) super.add(e) } abstract override def remove(e: String) = { println(“Remove :“ + e) super.remove(e) } }
  • 45. Run the stack of interceptors val set = new java.util.HashSet[String] with IgnoreCaseSet with LoggableSet set.add(“HI THERE“)  “Add: HI THERE” Prints in uppercase
  • 46. Change the order val set = new java.util.HashSet[String] with LoggableSet with IgnoreCaseSet set.add(“HI THERE“)  “Add: hi there” Prints in lowercase
  • 47. 3
  • 48. Multiple views Trait Trait Trait Trait Base Trait
  • 49. Multiple views Trait Trait Trait Trait Base Trait
  • 51. Traits Multiple facets
  • 53. Facets trait Entity { ... } trait InventoryItemSet { ... } trait Invoicable { ... } trait PurchaseLimiter { ... } trait MailNotifier { ... } trait ACL { ... } trait Versioned { ... } trait Transactional { ... }
  • 54. Composition val order = new Order(customer) with Entity with InventoryItemSet with Invoicable with PurchaseLimiter with MailNotifier with ACL with Versioned with Transactional
  • 55. What do you need?
  • 56. DI
  • 59. Dependency declaration trait UserService { this: UserRepository => ... // provided with composition userRepository.merge(user) } …using self-type annotation
  • 60.
  • 62. walks like a duck… if it and talks like a duck… then it’s a duck Duck typing
  • 63. Structural Typing: Duck-typing done right def authorize(target: { def getACL: ACL }) = { val acl = target.getACL ... //authorize } Statically enforced
  • 64. Composition in small
  • 65. “It's Time to Get Good at Functional Programming” Dr Dobb’s Journal Issue December 2008
  • 67. Deterministic Reusable High-level FP Referentially transparent Immutable Declarative Orthogonal
  • 69. Small reusable pieces input with output and
  • 70. Unix pipes cat File | grep 'println' | wc
  • 72. Functions as values val inc = (x: Int) => x + 1 inc(1) 2
  • 73. Functions as parameters high-order List(1, 2, 3).map((x: Int) => x + 1)  List(2, 3, 4)
  • 74. Functions as parameters with sugar List(1, 2, 3).map((x: Int) => x + 1) List(1, 2, 3).map(x => x + 1) List(1, 2, 3).map(_ + 1)
  • 75. Functions as closures val addMore = (x: Int) => x + more
  • 77. Some value outside the function’s lexical scope var more = 7 val addMore = (x: Int) => x + more addMore(3)  10 more = 8 addMore(3)  11
  • 81. Lists Grow at the front Insert at front  O(1) Insert at end  O(n)
  • 82. List creation List(1, 2, 3) 1 :: 2 :: 3 :: Nil
  • 83. Basics val list = List(1, 2, 3) list.head 1 list.tail  List(2, 3) list.isEmpty  false
  • 84. High-level operations val list = List(1, 2, 3) list.map(_ + 1)  List(2, 3, 4) list.filter(_ < 2)  List(3) list.exists(_ == 3)  true list.drop(2)  List(3) list.reverse  List(3, 2, 1) list.sort(_ > _)  List(3, 2, 1) List.flatten(list)  List(1, 2, 3) list.slice(2, 3)  List(3) ...
  • 85. 115 List functions defined on
  • 86. Tuples def getNameAndAge: Tuple2[String, Int] = { val name = ... val age = ... (name, age) } val (name, age) = getNameAndAge println(“Name: “ + name) println(“Age: “ + age)
  • 87. Other functional data structures: Maps Sets Trees Stacks
  • 88. For comprehensions for (n <- names) println(n)
  • 89. Like SQL queries for { att <- attendees if att.name == “Fred” lang <- att.spokenLanguages if lang == “Danish” } println(att) Find all attendees named Fred that speaks Danish
  • 90. for / yield val companiesForAttendeesFromLondon = for { att <- attendees if att.address.city == “London” } yield att.company
  • 91. Everything returns a value for (thing <- thingsFromHere) yield getRealThing(thing)
  • 92. Everything returns a value val things = for (thing <- thingsFromHere) yield getRealThing(thing)
  • 93. Everything returns a value if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { for (thing <- thingsFromThere) yield thing }
  • 94. Everything returns a value val things = if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { for (thing <- thingsFromThere) yield thing }
  • 95. Everything returns a value try { if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { for (thing <- thingsFromThere) yield thing } } catch { case e => error(e); Nil }
  • 96. Everything returns a value val things = try { if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { for (thing <- thingsFromThere) yield thing } } catch { case e => error(e); Nil }
  • 97. Everything returns a value def getThingsFromSomewhere( fromHere: Boolean): List[Thing] = { try { if (fromHere) { for (thing <- thingsFromHere) yield getRealThing(thing) } else { for (thing <- thingsFromThere) yield thing } } catch { case e => error(e); Nil } }
  • 99. Pattern matching def matchAny(a: Any): Any = a match { case 1 => “one” case “two” => 2 case i: Int => “scala.Int” case <tag>{ t }</tag> => t case head :: tail => head case _ => “default” }
  • 100. Tools
  • 101. Tools: scala/bin scala scalac fsc scaladoc sbaz
  • 102. Tools: IDEs Eclipse NetBeans IntelliJ IDEA Emacs JEdit
  • 103. Building Maven Ant SBT (Simple Build Tool )
  • 104. Tools: Testing Specs ScalaCheck ScalaTest SUnit
  • 105. Frameworks: Web Lift Sweet Slinky Pinky
  • 106. Learn more jonas@jonasboner.com http://jonasboner.com http://scala-lang.org
  • 107. Professional help Consulting Training Mentoring http://scalablesolutions.se
  • 108. Pragmatic Real-World Scala Jonas Bonér Scalable Solutions Copyright 2009 Scalable Solutions