KEMBAR78
Scala for ruby programmers | KEY
scala
dla programistów ruby :)



   Tymon Tobolski
   http://teamon.eu
Scala - ???

• OOP + FP
• statycznie typowany
• kompilowany do JVM
• intergacja z Java
scala jest trudna
trait FilterMonadic[+A, +Repr] {
  def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
  // ...
}

def zipWithIndexIf[T](list: List[T])(pred: T => Boolean): List[(T, Option[Int])] = {
    type R = List[(T, Option[Int])]
    def doZip(zipped: R, left: List[T], index: Int): R = left match {
        case x :: xs if pred(x) => doZip((x, Some(index)) :: zipped, xs, index + 1)
        case x :: xs => doZip((x, None) :: zipped, xs, index)
        case Nil => zipped
    }

    doZip(Nil, list, 0).reverse
}
scala jest trudna
trait FilterMonadic[+A, +Repr] {
  def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
  // ...
}

def zipWithIndexIf[T](list: List[T])(pred: T => Boolean): List[(T, Option[Int])] = {
    type R = List[(T, Option[Int])]
    def doZip(zipped: R, left: List[T], index: Int): R = left match {
        case x :: xs if pred(x) => doZip((x, Some(index)) :: zipped, xs, index + 1)
        case x :: xs => doZip((x, None) :: zipped, xs, index)
        case Nil => zipped
    }

    doZip(Nil, list, 0).reverse
}
serio?
List(1,2,3) map { e => e * 2 } // List[Int] = List(2, 4, 6)
serio?
List(1,2,3) map { e => e * 2 } // List[Int] = List(2, 4, 6)

List(1,2,3) map (_*2) // List[Int] = List(2, 4, 6)

List(1,2,3) map (2*) // List[Int] = List(2, 4, 6)

List(1,2,3) filter { _ > 1 } // List[Int] = List(2, 3)

(1 to 10) foreach { e => println(e) }

(1 to 10) foreach println
Monkey patching


      2.days
Monkey patching
  Implicit
conversions
implicit def Int2Time(i: Int) = new {
  def days = i * 24* 60 * 60
}

2.days // 172800
Modules / Traits
module T1
  def foo
    "foo"
  end
end

module T2
  def bar
    "bar"
  end
end

class A
  include T1
  include T2
end

a = A.new
a.foo # => "foo"
a.bar # => "bar"
Modules / Traits
module T1
  def foo
    "foo"
  end
                   trait T1 {
end
                     def foo = "foo"
                   }
module T2
  def bar
                   trait T2 {
    "bar"
                     def bar = "bar"
  end
                   }
end
                   class A extends T1 with T2
class A
  include T1
                   val a = new A
  include T2
                   a.foo // "foo"
end
                   a.bar // "bar"
a = A.new
a.foo # => "foo"
a.bar # => "bar"
Singleton
class A
  def foo
    "instance"
  end
  
  class << self
    def foo
      "singleton"
    end
  end
end

A.new.foo # => "instance"
A.foo     # => "singleton"
Singleton
class A
  def foo
    "instance"               class A {
  end                          def foo = "instance"
                             }
  class << self
    def foo                  object A {
      "singleton"              def foo "singleton"
    end                      }
  end
end                          new A().foo // "instance"
                             A.foo       // "singleton"
A.new.foo # => "instance"
A.foo     # => "singleton"
Duck typing
class Duck
  def quack
  def walk
end

class Dove
  def quack
  def walk
end

class Cat
end

def quack_and_walk(animal)
  animal.quack
  animal.walk
end

quack_and_walk Duck.new
quack_and_walk Dove.new
quack_and_walk Cat.new # NoMethodError
Duck typing
class Duck                               class Duck {
  def quack                                def quack
  def walk                                 def walk
end                                      }

class Dove                               class Dove {
  def quack                                def quack
  def walk                                 def walk
end                                      }

class Cat                                class Cat
end
                                         def quackAndWalk(a: { def quack; def walk }) = {
def quack_and_walk(animal)                 a.quack
  animal.quack                             a.walk
  animal.walk                            }
end
                                         quackAndWalk(new Duck)
quack_and_walk Duck.new                  quackAndWalk(new Dove)
quack_and_walk Dove.new                  quackAndWalk(new Cat) // Compile error
quack_and_walk Cat.new # NoMethodError
DSL
class StackSpec extends FlatSpec with ShouldMatchers {

  "A Stack" should "pop values in last-in-first-out order" in {
    val stack = new Stack[Int]
    stack.push(1)
    stack.push(2)
    stack.pop() should equal (2)
    stack.pop() should equal (1)
  }

  it should "throw NoSuchElementException if an empty stack is popped" in {
    val emptyStack = new Stack[String]
    evaluating { emptyStack.pop() } should produce [NoSuchElementException]
  }
}




                             http://scalatest.org
DSL
class FilterExample extends ScalatraFilter {
  get("/hello") {
    <p>
      Hello world
    </p>
  }

  post("/world") {
    // ...
  }
}



           https://github.com/scalatra/scalatra
Immutability

val list = List(2, 3)
val list2 = 1 :: list

println(list) // List(2, 3)
println(list2) // List(1, 2, 3)
Built-in concurency
scala> (1 to 10) foreach println
1
2
3
4
5
6
7
8
9
10
Built-in concurency
scala> (1 to 10).par foreach println
1
2
3
4
5
8
9
10
6
7
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> Map(1 -> 2) get _
res10: (Int) => Option[Int] = <function1>
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> Map(1 -> 2) get _
res10: (Int) => Option[Int] = <function1>
scala> Map(1 -> 2) get 1
res11: Option[Int] = Some(2)
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> Map(1 -> 2) get _
res10: (Int) => Option[Int] = <function1>
scala> Map(1 -> 2) get 1
res11: Option[Int] = Some(2)
scala> Map(1 -> 2) get 3
res12: Option[Int] = None
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> Map(1 -> 2) get _
res10: (Int) => Option[Int] = <function1>
scala> Map(1 -> 2) get 1
res11: Option[Int] = Some(2)
scala> Map(1 -> 2) get 3
res12: Option[Int] = None
scala> Map(1 -> 2) get 1 map (1+)
res13: Option[Int] = Some(3)
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> Map(1 -> 2) get _
res10: (Int) => Option[Int] = <function1>
scala> Map(1 -> 2) get 1
res11: Option[Int] = Some(2)
scala> Map(1 -> 2) get 3
res12: Option[Int] = None
scala> Map(1 -> 2) get 1 map (1+)
res13: Option[Int] = Some(3)
scala> Map(1 -> 2) get 3 map (1+)
res14: Option[Int] = None
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> Map(1 -> 2) get _
res10: (Int) => Option[Int] = <function1>
scala> Map(1 -> 2) get 1
res11: Option[Int] = Some(2)
scala> Map(1 -> 2) get 3
res12: Option[Int] = None
scala> Map(1 -> 2) get 1 map (1+)
res13: Option[Int] = Some(3)
scala> Map(1 -> 2) get 3 map (1+)
res14: Option[Int] = None
scala> Map(1 -> 2) get 1 map (1+) getOrElse 5
res15: Int = 3
Functional style
scala> Map(1 -> 2)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> Map(1 -> 2) get _
res10: (Int) => Option[Int] = <function1>
scala> Map(1 -> 2) get 1
res11: Option[Int] = Some(2)
scala> Map(1 -> 2) get 3
res12: Option[Int] = None
scala> Map(1 -> 2) get 1 map (1+)
res13: Option[Int] = Some(3)
scala> Map(1 -> 2) get 3 map (1+)
res14: Option[Int] = None
scala> Map(1 -> 2) get 1 map (1+) getOrElse 5
res15: Int = 3
scala> Map(1 -> 2) get 3 map (1+) getOrElse 5
res16: Int = 5
Web

                  • Play!
• Rails
                  • Lift
• Sinatra
                  • Scalatra
• ...
                  • ...
• Actors
• STM
• Fault Tolerance
• ...
• http://scala-lang.org
• http://akka.io
• http://typesafe.com
• http://scala.playframework.org/

• #scala @ irc.freenode.net
• #scala.pl @ irc.freenode.net

Scala for ruby programmers

  • 1.
    scala dla programistów ruby:) Tymon Tobolski http://teamon.eu
  • 2.
    Scala - ??? •OOP + FP • statycznie typowany • kompilowany do JVM • intergacja z Java
  • 3.
    scala jest trudna traitFilterMonadic[+A, +Repr] {   def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That   // ... } def zipWithIndexIf[T](list: List[T])(pred: T => Boolean): List[(T, Option[Int])] = {     type R = List[(T, Option[Int])]     def doZip(zipped: R, left: List[T], index: Int): R = left match {         case x :: xs if pred(x) => doZip((x, Some(index)) :: zipped, xs, index + 1)         case x :: xs => doZip((x, None) :: zipped, xs, index)         case Nil => zipped     }     doZip(Nil, list, 0).reverse }
  • 4.
    scala jest trudna traitFilterMonadic[+A, +Repr] {   def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That   // ... } def zipWithIndexIf[T](list: List[T])(pred: T => Boolean): List[(T, Option[Int])] = {     type R = List[(T, Option[Int])]     def doZip(zipped: R, left: List[T], index: Int): R = left match {         case x :: xs if pred(x) => doZip((x, Some(index)) :: zipped, xs, index + 1)         case x :: xs => doZip((x, None) :: zipped, xs, index)         case Nil => zipped     }     doZip(Nil, list, 0).reverse }
  • 5.
    serio? List(1,2,3) map {e => e * 2 } // List[Int] = List(2, 4, 6)
  • 6.
    serio? List(1,2,3) map {e => e * 2 } // List[Int] = List(2, 4, 6) List(1,2,3) map (_*2) // List[Int] = List(2, 4, 6) List(1,2,3) map (2*) // List[Int] = List(2, 4, 6) List(1,2,3) filter { _ > 1 } // List[Int] = List(2, 3) (1 to 10) foreach { e => println(e) } (1 to 10) foreach println
  • 7.
  • 8.
    Monkey patching Implicit conversions implicit def Int2Time(i: Int) = new { def days = i * 24* 60 * 60 } 2.days // 172800
  • 9.
    Modules / Traits moduleT1   def foo     "foo"   end end module T2   def bar     "bar"   end end class A   include T1   include T2 end a = A.new a.foo # => "foo" a.bar # => "bar"
  • 10.
    Modules / Traits moduleT1   def foo     "foo"   end trait T1 { end   def foo = "foo" } module T2   def bar trait T2 {     "bar"   def bar = "bar"   end } end class A extends T1 with T2 class A   include T1 val a = new A   include T2 a.foo // "foo" end a.bar // "bar" a = A.new a.foo # => "foo" a.bar # => "bar"
  • 11.
    Singleton class A   def foo     "instance"   end      class<< self     def foo       "singleton"     end   end end A.new.foo # => "instance" A.foo # => "singleton"
  • 12.
    Singleton class A   def foo     "instance" class A {   end   def foo = "instance"    }   class << self     def foo object A {       "singleton"   def foo "singleton"     end }   end end new A().foo // "instance" A.foo // "singleton" A.new.foo # => "instance" A.foo # => "singleton"
  • 13.
    Duck typing class Duck   defquack   def walk end class Dove   def quack   def walk end class Cat end def quack_and_walk(animal)   animal.quack   animal.walk end quack_and_walk Duck.new quack_and_walk Dove.new quack_and_walk Cat.new # NoMethodError
  • 14.
    Duck typing class Duck class Duck {   def quack   def quack   def walk   def walk end } class Dove class Dove {   def quack   def quack   def walk   def walk end } class Cat class Cat end def quackAndWalk(a: { def quack; def walk }) = { def quack_and_walk(animal)   a.quack   animal.quack   a.walk   animal.walk } end quackAndWalk(new Duck) quack_and_walk Duck.new quackAndWalk(new Dove) quack_and_walk Dove.new quackAndWalk(new Cat) // Compile error quack_and_walk Cat.new # NoMethodError
  • 15.
    DSL class StackSpec extendsFlatSpec with ShouldMatchers {   "A Stack" should "pop values in last-in-first-out order" in {     val stack = new Stack[Int]     stack.push(1)     stack.push(2)     stack.pop() should equal (2)     stack.pop() should equal (1)   }   it should "throw NoSuchElementException if an empty stack is popped" in {     val emptyStack = new Stack[String]     evaluating { emptyStack.pop() } should produce [NoSuchElementException]   } } http://scalatest.org
  • 16.
    DSL class FilterExample extendsScalatraFilter {   get("/hello") {     <p>       Hello world     </p>   }   post("/world") { // ...   } } https://github.com/scalatra/scalatra
  • 17.
    Immutability val list =List(2, 3) val list2 = 1 :: list println(list) // List(2, 3) println(list2) // List(1, 2, 3)
  • 18.
    Built-in concurency scala> (1to 10) foreach println 1 2 3 4 5 6 7 8 9 10
  • 19.
    Built-in concurency scala> (1to 10).par foreach println 1 2 3 4 5 8 9 10 6 7
  • 20.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
  • 21.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> Map(1 -> 2) get _ res10: (Int) => Option[Int] = <function1>
  • 22.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> Map(1 -> 2) get _ res10: (Int) => Option[Int] = <function1> scala> Map(1 -> 2) get 1 res11: Option[Int] = Some(2)
  • 23.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> Map(1 -> 2) get _ res10: (Int) => Option[Int] = <function1> scala> Map(1 -> 2) get 1 res11: Option[Int] = Some(2) scala> Map(1 -> 2) get 3 res12: Option[Int] = None
  • 24.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> Map(1 -> 2) get _ res10: (Int) => Option[Int] = <function1> scala> Map(1 -> 2) get 1 res11: Option[Int] = Some(2) scala> Map(1 -> 2) get 3 res12: Option[Int] = None scala> Map(1 -> 2) get 1 map (1+) res13: Option[Int] = Some(3)
  • 25.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> Map(1 -> 2) get _ res10: (Int) => Option[Int] = <function1> scala> Map(1 -> 2) get 1 res11: Option[Int] = Some(2) scala> Map(1 -> 2) get 3 res12: Option[Int] = None scala> Map(1 -> 2) get 1 map (1+) res13: Option[Int] = Some(3) scala> Map(1 -> 2) get 3 map (1+) res14: Option[Int] = None
  • 26.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> Map(1 -> 2) get _ res10: (Int) => Option[Int] = <function1> scala> Map(1 -> 2) get 1 res11: Option[Int] = Some(2) scala> Map(1 -> 2) get 3 res12: Option[Int] = None scala> Map(1 -> 2) get 1 map (1+) res13: Option[Int] = Some(3) scala> Map(1 -> 2) get 3 map (1+) res14: Option[Int] = None scala> Map(1 -> 2) get 1 map (1+) getOrElse 5 res15: Int = 3
  • 27.
    Functional style scala> Map(1-> 2) res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2) scala> Map(1 -> 2) get _ res10: (Int) => Option[Int] = <function1> scala> Map(1 -> 2) get 1 res11: Option[Int] = Some(2) scala> Map(1 -> 2) get 3 res12: Option[Int] = None scala> Map(1 -> 2) get 1 map (1+) res13: Option[Int] = Some(3) scala> Map(1 -> 2) get 3 map (1+) res14: Option[Int] = None scala> Map(1 -> 2) get 1 map (1+) getOrElse 5 res15: Int = 3 scala> Map(1 -> 2) get 3 map (1+) getOrElse 5 res16: Int = 5
  • 28.
    Web • Play! • Rails • Lift • Sinatra • Scalatra • ... • ...
  • 29.
    • Actors • STM •Fault Tolerance • ...
  • 30.
    • http://scala-lang.org • http://akka.io •http://typesafe.com • http://scala.playframework.org/ • #scala @ irc.freenode.net • #scala.pl @ irc.freenode.net