SlideShare uma empresa Scribd logo
1 de 243
Scala:
Demystifying The
Funky Stuff
Daniel Hinojosa
Email: dhinojosa@evolutionnext.com
Twitter: @dhinojosa Google+: gplus.to/dhinojosa
The Goal

“To make Scala less mysterious, less intimidating”
Funky def.




Funky(slang): strange, far out
Are you interested?
●   Covers some of the harder Scala concepts
●   Predef and package objects
●   Types, Abstract Types & Type Projections
●   implicit Parameters, Converters, Wrappers
●   Manifests
●   Type Variances and Bounds
●   Other goodness
Predef
Predef
●   scala.Predef object
●   Automatically available since scala package is
    automatically included.
●   Contains commons type aliases, and implicits
    (to be discussed)
Types, Abstract Types and Type
         Projections
Types

type Goober = Int
val x:Goober = 3
Types

class Foo {
  class Bar {}
}

val foo = new Foo()
val bar = new foo.Bar()
Types

  class Foo {
    class Bar {}
  }

  val foo = new Foo()
  val bar = new foo.Bar()

* As opposed to Java, Inner objects belong to the
  Outer Object not the outer class
Types

class Foo {
  class Bar {}
}

val foo = new Foo()
val bar:Foo#Bar = new foo.Bar()
val bar:foo.Bar = new foo.Bar()
Types

class Foo {
  class Bar {}
}

val foo = new Foo()
val bar:Foo#Bar = new foo.Bar()
val bar:foo.Bar = new foo.Bar()
Types

class Foo {
  class Bar {}
}

val foo = new Foo()
val bar:Foo#Bar = new foo.Bar()
val bar:foo.Bar = new foo.Bar()
Types

class Foo {
  class Bar {}
}

val foo = new Foo()
val bar:Foo#Bar = new foo.Bar()
val bar:foo.Bar = new foo.Bar()
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

val favoriteDrink: SomeSingleton.type =
                   SomeSingleton

favoriteDrink.z // Grande Latte"
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

val favoriteDrink: SomeSingleton.type =
                   SomeSingleton

favoriteDrink.z // Grande Latte"
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

val favoriteDrink: SomeSingleton.type =
                   SomeSingleton

favoriteDrink.z // Grande Latte"
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

val favoriteDrink: SomeSingleton.type =
                   SomeSingleton

favoriteDrink.z // Grande Latte"
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

def drink(x:SomeSingleton.type) {
   x.z should be ("Grande Latte")
}

drink(SomeSingleton)
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

def drink(x:SomeSingleton.type) {
   x.z should be ("Grande Latte")
}

drink(SomeSingleton)
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

def drink(x:SomeSingleton.type) {
   x.z should be ("Grande Latte")
}

drink(SomeSingleton)
Stable/Singleton Type
object SomeSingleton {
   val z = "Grande Latte"
}

def drink(x:SomeSingleton.type) {
   x.z should be ("Grande Latte")
}

drink(SomeSingleton)
Stable/Singleton Type
case class Celebrity(firstName:String,
                lastName:String)

val tomHanks = new Celebrity("Tom", "Hanks")
val jodieFoster = new Celebrity("Jodie",
"Foster")
val tomHanksImposter =
                 new Celebrity("Tom", "Hanks")

def enterTomHanksHouse(x:tomHanks.type) {}
Stable/Singleton Type
class Celebrity(firstName:String,
                lastName:String)

val tomHanks = new Celebrity("Tom", "Hanks")
val jodieFoster = Celebrity("Jodie", "Foster")
val tomHanksImposter =
                 new Celebrity("Tom", "Hanks")

def enterTomHanksHouse(x:tomHanks.type) {}
Stable/Singleton Type
class Celebrity(firstName:String,
                lastName:String)

val tomHanks = new Celebrity("Tom", "Hanks")
val jodieFoster = Celebrity("Jodie", "Foster")
val tomHanksImposter =
                 new Celebrity("Tom", "Hanks")

def enterTomHanksHouse(x:tomHanks.type) {}

enterTomHanksHouse(tomHanks) //OK
Stable/Singleton Type
class Celebrity(firstName:String,
                lastName:String)

val tomHanks = new Celebrity("Tom", "Hanks")
val jodieFoster = Celebrity("Jodie", "Foster")
val tomHanksImposter =
                 new Celebrity("Tom", "Hanks")

def enterTomHanksHouse(x:tomHanks.type) {}

enterTomHanksHouse(tomHanks) //OK
enterTomHanksHouse(jodieFoster) //Wrong
Stable/Singleton Type
class Celebrity(firstName:String,
                lastName:String)

val tomHanks = new Celebrity("Tom", "Hanks")
val jodieFoster = Celebrity("Jodie", "Foster")
val tomHanksImposter =
                 new Celebrity("Tom", "Hanks")

def enterTomHanksHouse(x:tomHanks.type) {}

enterTomHanksHouse(tomHanks) //OK
enterTomHanksHouse(jodieFoster) //Wrong
enterTomHanksHouse(tomHanksImposter) //Wrong
Abstract Types
abstract class Generator {
   type F
   def generate: F
}

class StringGenerator extends Generator {
   type F = String
   def generate = "Scooters are fun"
}

new StringGenerator().generate // Scooters are fun
Abstract Types
abstract class Generator {
   type F
   def generate: F
}

class StringGenerator extends Generator {
   type F = String
   def generate = "Scooters are fun"
}

new StringGenerator().generate // Scooters are fun
Abstract Types
abstract class Generator {
   type F
   def generate: F
}

class StringGenerator extends Generator {
   type F = String
   def generate = "Scooters are fun"
}

new StringGenerator().generate // Scooters are fun
Abstract Types
abstract class Generator {
   type F
   def generate: F
}

class StringGenerator extends Generator {
   type F = String
   def generate = "Scooters are fun"
}

new StringGenerator().generate // Scooters are fun
Abstract Types
abstract class Generator {
   type F
   def generate: F
}

class StringGenerator extends Generator {
   type F = String
   def generate = "Scooters are fun"
}

val x = new StringGenerator()
classOf[x.F] = class java.lang.String
classOf[x.type#F] = class java.lang.String
classOf[StringGenerator#F] = class java.lang.String
Abstract Types
abstract class Generator {
   type F
   def generate: F
}

class StringGenerator extends Generator {
   type F = String
   def generate = "Scooters are fun"
}

val x = new StringGenerator()
classOf[x.F] = class java.lang.String
classOf[x.type#F] = class java.lang.String
classOf[StringGenerator#F] = class java.lang.String

val w:x.F = “Oh yeah!”
val x:x.type#F = “Rock and Roll”
Abstract Types vs.
Parameterized Types?
Infix Types
Infix Types
case class Person(name: String)
class Loves[A, B](val a: A, val b: B)

def announceCouple
   (couple: Loves[Person, Person]) = {
    couple.a.name + " is in love with " +
                      couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(new Loves(romeo, juliet))
  //Romeo is in love with Juliet")
Infix Types
case class Person(name: String)
class Loves[A, B](val a: A, val b: B)

def announceCouple
   (couple: Loves[Person, Person]) = {
    couple.a.name + " is in love with " +
                      couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(new Loves(romeo, juliet))
  //Romeo is in love with Juliet")
Infix Types
case class Person(name: String)
class Loves[A, B](val a: A, val b: B)

def announceCouple
   (couple: Loves[Person, Person]) = {
    couple.a.name + " is in love with " +
                      couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(new Loves(romeo, juliet))
  //Romeo is in love with Juliet")
Infix Types
case class Person(name: String)
class Loves[A, B](val a: A, val b: B)

def announceCouple
   (couple: Person Loves Person) = {
    couple.a.name + " is in love with " +
                      couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(new Loves(romeo, juliet))
  //Romeo is in love with Juliet")
Infix Types
case class Person(name: String)
class Loves[A, B](val a: A, val b: B)

def announceCouple
   (couple: Person Loves Person) = {
    couple.a.name + " is in love with " +
                      couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(new Loves(romeo, juliet))
//Romeo is in love with Juliet
*It would be nice to say “romeo loves juliet”
Infix Types with Infix Operators
case class Person(name: String) {
   def loves(person: Person) =
      new Loves(this, person)
}
class Loves[A, B](val a: A, val b: B)

def announceCouple(couple: Person Loves Person) =
{
   couple.a.name + " is in love with " +
                   couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(romeo loves juliet)
//Romeo is in love with Juliet")
Infix Types with Infix Operators
case class Person(name: String) {
   def loves(person: Person) =
      new Loves(this, person)
}
class Loves[A, B](val a: A, val b: B)

def announceCouple(couple: Person Loves Person) =
{
   couple.a.name + " is in love with " +
                   couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(romeo loves juliet)
//Romeo is in love with Juliet")
Infix Types with Infix Operators
case class Person(name: String) {
   def loves(person: Person) =
      new Loves(this, person)
}
class Loves[A, B](val a: A, val b: B)

def announceCouple(couple: Person Loves Person) =
{
   couple.a.name + " is in love with " +
                   couple.b.name
}

val romeo = new Person("Romeo")
val juliet = new Person("Juliet")

announceCouple(romeo loves juliet)
//Romeo is in loveyou can omitJuliet param methods
 *Scala is a loose syntax language, with the () for one
implicit
implicit
parameters
implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
   dollarsPerHour: BigDecimal) =
   dollarsPerHour * hours
implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
   dollarsPerHour: BigDecimal) =
   dollarsPerHour * hours
implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
   dollarsPerHour: BigDecimal) =
    dollarsPerHour * hours

*last curried parameter
implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
   dollarsPerHour: BigDecimal) =
    dollarsPerHour * hours

implicit var hourlyRate = BigDecimal(34.00)

*implicit reference must be in scope to be satisfied
implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
   dollarsPerHour: BigDecimal) =
    dollarsPerHour * hours

implicit var hourlyRate = BigDecimal(34.00)

howMuchCanIMake_?(30)   //1020.00
implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
   dollarsPerHour: BigDecimal) =
    dollarsPerHour * hours

implicit var hourlyRate = BigDecimal(34.00)

howMuchCanIMake_?(30)   //1020.00

hourlyRate = BigDecimal(95.00) //reassigning
implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
   dollarsPerHour: BigDecimal) =
    dollarsPerHour * hours

implicit var hourlyRate = BigDecimal(34.00)

howMuchCanIMake_?(30)   //1020.00

hourlyRate = BigDecimal(95.00) //reassigning

howMuchCanIMake_?(95) //(9025.00)
multiple implicit parameters
multiple implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit amount:
                                  BigDecimal,
                                  currencyName: String) =
   (amount * hours).toString() + " " + currencyName
multiple implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit amount:
                                  BigDecimal,
                                  currencyName: String) =
   (amount * hours).toString() + " " + currencyName
multiple implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
                                  amount: BigDecimal,
                                  currencyName: String) =
   (amount * hours).toString() + " " + currencyName

implicit var hourlyRate = BigDecimal(34.00)
implicit val currencyName = "Dollars"
multiple implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
                                  amount: BigDecimal,
                                  currencyName: String) =
   (amount * hours).toString() + " " + currencyName

implicit var hourlyRate = BigDecimal(34.00)
implicit val currencyName = "Dollars"

howMuchCanIMake_?(30) // "1020.0 Dollars"
multiple implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
                                  amount: BigDecimal,
                                  currencyName: String) =
   (amount * hours).toString() + " " + currencyName

implicit var hourlyRate = BigDecimal(34.00)
implicit val currencyName = "Dollars"

howMuchCanIMake_?(30) // "1020.0 Dollars"

hourlyRate = BigDecimal(95.00)
multiple implicit parameters
def howMuchCanIMake_?(hours: Int)(implicit
                                  amount: BigDecimal,
                                  currencyName: String) =
   (amount * hours).toString() + " " + currencyName

implicit var hourlyRate = BigDecimal(34.00)
implicit val currencyName = "Dollars"

howMuchCanIMake_?(30) // "1020.0 Dollars"

hourlyRate = BigDecimal(95.00)

howMuchCanIMake_?(95) // "9025.0 Dollars"
default arguments instead of
          implicit
default arguments instead of
            implicit
def howMuchCanIMake_?(hours: Int,
                      amount: BigDecimal = 34,
                      currencyName: String ="Dollars") =
   (amount * hours).toString() + " " +
    currencyName
default arguments instead of
            implicit
def howMuchCanIMake_?(hours: Int,
                      amount: BigDecimal = 34,
                      currencyName: String ="Dollars") =
   (amount * hours).toString() + " " +
    currencyName

howMuchCanIMake_?(30) // 1020 Dollars
default arguments instead of
            implicit
def howMuchCanIMake_?(hours: Int,
                      amount: BigDecimal = 34,
                      currencyName: String ="Dollars") =
   (amount * hours).toString() + " " +
    currencyName

howMuchCanIMake_?(30) // 1020 Dollars

howMuchCanIMake_?(95, 95) // 9025 Dollars
default arguments instead of
            implicit
def howMuchCanIMake_?(hours: Int,
                      amount: BigDecimal = 34,
                      currencyName: String ="Dollars") =
   (amount * hours).toString() + " " +
    currencyName

howMuchCanIMake_?(30) // 1020 Dollars

howMuchCanIMake_?(95, 95) // 9025 Dollars

howMuchCanIMake_?(currencyName="Yen", amount=925, hours =
29) // 26825 Yen
implicit objects in implicit
        parameters
implicit objects in implicit
        parameters
case class Employee(firstName:String, lastName:String,
salary:Float)
implicit objects in implicit
        parameters
case class Employee(firstName:String, lastName:String,
salary:Float)

implicit object CEO extends Employee("Charo",
                                     "Frostycorn",
                                     499000.22f)
implicit objects in implicit
         parameters
case class Employee(firstName:String, lastName:String,
salary:Float)

implicit object CEO extends Employee("Charo",
                                     "Frostycorn",
                                     499000.22f)

def isEmployeePaidTooMuch_?(salary:Float)(implicit
modelEmployee:Employee) = salary > modelEmployee.salary

* Using floating point as currency used for demonstration purposes only.
Meta-programming
Monkey Patching in Ruby
             class Integer
               def squared
                 self * self
               end
             end

             >> 4.squared
             => 16




Source: http://paulbarry.com/articles/2009/04/17/implicit-conversions-scalas-type-safe-answer-to-rubys-open-class
Issues with Monkey Patching in
                   Ruby
       ● Other imports can override the your
         patch, effectively making
         debugging difficult.
       ● There are other ways of achieving

         the same effect. http://bit.ly/RBid2D




Source:http://www.rubyinside.com/the-end-of-monkeypatching-4570.html
Mopping in Groovy
class Integer
  def squared
    self * self
  end
end

>> 4.squared
=> 16
implicit wrappers
implicit wrappers
class MyIntWrapper(val original: Int) {
     def isOdd = original % 2 != 0
}
implicit wrappers
class MyIntWrapper(val original: Int) {
     def isOdd = original % 2 != 0
}

implicit def int2MyIntWrapper(value: Int) = new
IntWrapper(value)
implicit wrappers
class MyIntWrapper(val original: Int) {
     def isOdd = original % 2 != 0
}

implicit def int2MyIntWrapper(value: Int) = new
MyIntWrapper(value)
implicit wrappers
class MyIntWrapper(val original: Int) {
     def isOdd = original % 2 != 0
}

implicit def int2MyIntWrapper(value: Int) = new
MyIntWrapper(value)
implicit wrappers
class MyIntWrapper(val original: Int) {
     def isOdd = original % 2 != 0
}

implicit def int2MyIntWrapper(value: Int) = new
MyIntWrapper(value)
implicit wrappers
 class MyIntWrapper(val original: Int) {
      def isOdd = original % 2 != 0
 }

 implicit def int2MyIntWrapper(value: Int) = new
 MyIntWrapper(value)



* The implicit needs to be within the same scope it is to be used
implicit wrappers
class MyIntWrapper(val original: Int) {
     def isOdd = original % 2 != 0
}

implicit def int2MyIntWrapper(value: Int) = new
MyIntWrapper(value)

19.isOdd // true
20.isOdd // false
implicit converters
implicit converters
import java.math.BigInteger

implicit def int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)
implicit converters
import java.math.BigInteger

implicit def int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)
implicit converters
import java.math.BigInteger

implicit def int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)
implicit converters
import java.math.BigInteger

implicit def int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)
implicit converters
import java.math.BigInteger

implicit def int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)
implicit converters
import java.math.BigInteger

implicit def Int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)
implicit converters
import java.math.BigInteger

implicit def Int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)

def add(a: BigInteger, b: BigInteger) = a.add(b)
implicit converters
import java.math.BigInteger

implicit def Int2BigIntegerConvert(value: Int) =
new BigInteger(value.toString)

def add(a: BigInteger, b: BigInteger) = a.add(b)

add(3, 6) // new BigInteger("9"))
implicit converters with functions
import java.math.BigInteger

implicit val int2BigIntegerConvert = (value:
Int) => new BigInteger(value.toString)

def add(a: BigInteger, b: BigInteger) = a.add(b)

add(3, 6) // new BigInteger("9"))
implicit converters with functions
import java.math.BigInteger

implicit val int2BigIntegerConvert = (value:
Int) => new BigInteger(value.toString)

def add(a: BigInteger, b: BigInteger) = a.add(b)

add(3, 6) // new BigInteger("9"))
Where do implicits come from
   other than declarations?
Importing implicits
object MyPredef {

   class MyIntWrapper(val original: Int) {
     def isOdd() = original % 2 != 0

       def isEven() = !isOdd()
   }

   implicit def int2MyIntWrapper(value: Int) =
       new MyIntWrapper(value)
}
import MyPredef._

19.isOdd() // true
20.isOdd() // false
Importing implicits
object MyPredef {

   class MyIntWrapper(val original: Int) {
     def isOdd() = original % 2 != 0

       def isEven() = !isOdd()
   }

   implicit def int2MyIntWrapper(value: Int) =
       new MyIntWrapper(value)
}
import MyPredef._

19.isOdd() // true
20.isOdd() // false
Importing implicits
object MyPredef {

   class MyIntWrapper(val original: Int) {
     def isOdd() = original % 2 != 0

       def isEven() = !isOdd()
   }

   implicit def int2MyIntWrapper(value: Int) =
       new MyIntWrapper(value)
}
import MyPredef._

19.isOdd() // true
20.isOdd() // false
Importing implicits
object MyPredef {

   class MyIntWrapper(val original: Int) {
     def isOdd() = original % 2 != 0

       def isEven() = !isOdd()
   }

   implicit def int2MyIntWrapper(value: Int) =
       new MyIntWrapper(value)
}
import MyPredef._

19.isOdd() // true
20.isOdd() // false
Importing implicits
object MyPredef {

   class MyIntWrapper(val original: Int) {
     def isOdd() = original % 2 != 0

       def isEven() = !isOdd()
   }

   implicit def int2MyIntWrapper(value: Int) =
       new MyIntWrapper(value)
}
import MyPredef._

19.isOdd() // true
20.isOdd() // false
Importing implicits
object MyPredef {

   class MyIntWrapper(val original: Int) {
     def isOdd() = original % 2 != 0

       def isEven() = !isOdd()
   }

   implicit def int2MyIntWrapper(value: Int) =
       new MyIntWrapper(value)
}
import MyPredef._

19.isOdd() // true
20.isOdd() // false
Companion implicits
class StringNumbering(val s:String, val i:Int) {
  override def toString = s
  def + (other:StringNumbering) = other.i + i
}

object StringNumbering {
  implicit def fromInt(i:Int):StringNumbering =
         new StringNumbering("Unknown", I)
  implicit def fromSnToInt(sn:StringNumbering):Int = sn.i
}

val numberOne = new StringNumbering("One", 1)
(numberOne + 3) // 4
(3 + numberOne) // 4
Companion implicits
class StringNumbering(val s:String, val i:Int) {
  override def toString = s
  def + (other:StringNumbering) = other.i + i
}

object StringNumbering {
  implicit def fromInt(i:Int):StringNumbering =
         new StringNumbering("Unknown", I)
  implicit def fromSnToInt(sn:StringNumbering):Int = sn.i
}

val numberOne = new StringNumbering("One", 1)
(numberOne + 3) // 4
(3 + numberOne) // 4
Companion implicits
class StringNumbering(val s:String, val i:Int) {
  override def toString = s
  def + (other:StringNumbering) = other.i + i
}

object StringNumbering {
  implicit def fromInt(i:Int):StringNumbering =
         new StringNumbering("Unknown", I)
  implicit def fromSnToInt(sn:StringNumbering):Int = sn.i
}

val numberOne = new StringNumbering("One", 1)
(numberOne + 3) // 4
(3 + numberOne) // 4
Companion implicits
class StringNumbering(val s:String, val i:Int) {
  override def toString = s
  def + (other:StringNumbering) = other.i + i
}

object StringNumbering {
  implicit def fromInt(i:Int):StringNumbering =
         new StringNumbering("Unknown", i)
  implicit def fromSnToInt(sn:StringNumbering):Int = sn.i
}

val numberOne = new StringNumbering("One", 1)
(numberOne + 3) // 4
(3 + numberOne) // 4
Companion implicits
class StringNumbering(val s:String, val i:Int) {
  override def toString = s
  def + (other:StringNumbering) = other.i + i
}

object StringNumbering {
  implicit def fromInt(i:Int):StringNumbering =
         new StringNumbering("Unknown", I)
  implicit def fromSnToInt(sn:StringNumbering):Int = sn.i
}

val numberOne = new StringNumbering("One", 1)
(numberOne + 3) // 4
(3 + numberOne) // 4
package implicits
package com.xyzcorp

package object abcproject {
   implicit val preferredAppliance =
         new Appliance("Dryer", "Gas")
}
In file com/xyzcorp/project/package.scala



package com.xyzcorp.abcproject;

class Appliance(val name: String, val powerType: String)
class SomeClass {
    def foo (implicit v:Appliance) {
        println(v.name) //Dryer
    }
}
In file com/xyzcorp/abcproject/SomeClass.scala
package implicits
package com.xyzcorp

package object abcproject {
   implicit val preferredAppliance =
         new Appliance("Dryer", "Gas")
}
In file com/xyzcorp/project/package.scala



package com.xyzcorp.abcproject;

class Appliance(val name: String, val powerType: String)
class SomeClass {
    def foo (implicit v:Appliance) {
        println(v.name) //Dryer
    }
}
In file com/xyzcorp/abcproject/SomeClass.scala
package implicits
package com.xyzcorp

package object abcproject {
   implicit val preferredAppliance =
         new Appliance("Dryer", "Gas")
}
In file com/xyzcorp/project/package.scala



package com.xyzcorp.abcproject;

class Appliance(val name: String, val powerType: String)
class SomeClass {
    def foo (implicit v:Appliance) {
        println(v.name) //Dryer
    }
}
In file com/xyzcorp/abcproject/SomeClass.scala
package implicits
package com.xyzcorp

package object abcproject {
   implicit val preferredAppliance =
         new Appliance("Dryer", "Gas")
}
In file com/xyzcorp/project/package.scala



package com.xyzcorp.abcproject;

class Appliance(val name: String, val powerType: String)
class SomeClass {
    def foo (implicit v:Appliance) {
        println(v.name) //Dryer
    }
}
In file com/xyzcorp/abcproject/SomeClass.scala
implicitly[]
implicitly[]
●   Contained within Predef
●   Returns the implicit object (includes functions)
    that is currently with scope at moment of
    request.
implicitly[]
implicit val secretOfLife=42

implicitly[Int] // 42
implicitly[]
implicit val secretOfLife=42

implicitly[Int] // 42
implicitly[]
implicit val secretOfLife=42

implicitly[Int] // 42
implicitly[]
implicitly[[Ordering[Int]] //From Predef
implicitly[]
implicitly[[Ordering[Int]] //From Predef

scala.math.Ordering$Int$@5aa77506
Manifests
Manifests

def inspect[T](l: List[T])
              (implicit manifest:Manifest[T])
              = manifest.toString

val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
inspect(list) // Int
Manifests

def inspect[T](l: List[T])
              (implicit manifest:Manifest[T])
              = manifest.toString

val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
inspect(list) // Int
Manifests

def inspect[T](l: List[T])
              (implicit manifest:Manifest[T])
              = manifest.toString

val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil
inspect(list) // Int
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]{
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]{
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]){
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]){
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]{
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]{
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]{
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests
case class Monkey(name: String)

class Barrel[T](implicit m:scala.reflect.Manifest[T]{
    def +(t: T) = "1 %s has been
        added".format(m.erasure.getSimpleName)
}

val monkeyBarrel = new Barrel[Monkey]
monkeyBarrel + new Monkey("Shotgun")

// "1 Monkey has been added"
Manifests

*Code Smell: Use Sparingly
Type Variances
The Setup
trait Fruit

abstract class Citrus extends Fruit

class Orange extends Citrus

class Tangelo extends Citrus

class Apple extends Fruit

class Banana extends Fruit

class NavelOrange extends Fruit
Simple Invariant Case
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents =
         manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer(new Orange())
fruitBasket.contents // Orange
Simple Invariant Case
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents =
         manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer(new Orange())
fruitBasket.contents // Orange
Simple Invariant Case
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents =
         manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer(new Orange())
fruitBasket.contents // Orange
Simple Invariant Case
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents =
         manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer(new Orange())
fruitBasket.contents // Orange
Explicitly Declaring Type
class MyContainer[A](a: A)
                     (implicit manifest:
                     scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer[Fruit]
                 (new Orange()) //Explicit call

fruitBasket.contents // Fruit - static type
Explicitly Declaring Type
class MyContainer[A](a: A)
                     (implicit manifest:
                     scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer[Fruit]
                 (new Orange()) //Explicit call

fruitBasket.contents // Fruit - static type
Explicitly Declaring Type Differently
class MyContainer[A](a: A)
                    (implicit manifest:
                     scala.reflect.Manifest[A]) {
        private[this] var item = a
        def get = item
        def set(a: A) {item = a}
        def contents =
            manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer(new
                  Orange():Fruit) //Explicit call
fruitBasket.contents // "Fruit" - static type
Explicitly Declaring Type Differently
class MyContainer[A](a: A)
                    (implicit manifest:
                     scala.reflect.Manifest[A]) {
        private[this] var item = a
        def get = item
        def set(a: A) {item = a}
        def contents =
            manifest.erasure.getSimpleName
}

val fruitBasket = new MyContainer(new
                  Orange():Fruit) //Explicit call
fruitBasket.contents // "Fruit" - static type
Explicitly Type Coersion
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer(new Orange())//Coerced

fruitBasket.contents // "Fruit"
Explicitly Type Coersion
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer(new Orange())//Coerced

fruitBasket.contents // "Fruit"
Explicitly Type Coersion
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer(new Orange())//Coerced

fruitBasket.contents // "Fruit"
*Based on the expected type it fills it in with type inference
Attempting Polymorphism
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket:MyContainer[Fruit] = new
MyContainer[Orange](new Orange())
Attempting Polymorphism
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] var item = a
      def get = item
      def set(a: A) {item = a}
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket:MyContainer[Fruit] = new
MyContainer[Orange](new Orange())
[error]   type mismatch;
[error]   found   : MyContainer[Orange]
[error]   required: MyContainer[Fruit]
Covariance
Covariance
class MyContainer[+A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer[Orange](new Orange())
fruitBasket.contents // Orange
Covariance
class MyContainer[+A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer[Orange](new Orange())
fruitBasket.contents // Orange
Covariance
class MyContainer[+A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer[Orange](new Orange())
fruitBasket.contents // Orange

*There is something missing
*No Method Parameters
Covariance
class MyContainer[+A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents = manifest.erasure.getSimpleName
}

class NavelOrange extends Orange

val navelOrangeBasket: MyContainer[NavelOrange] =
    new MyContainer[Orange](new Orange()) //Bad!

val tangeloBasket: MyContainer[Tangelo] = new
    MyContainer[Orange](new Orange()) //Bad!
Covariance
class MyContainer[+A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents = manifest.erasure.getSimpleName
}

class NavelOrange extends Orange

val navelOrangeBasket: MyContainer[NavelOrange] =
    new MyContainer[Orange](new Orange()) //Bad!

val tangeloBasket: MyContainer[Tangelo] = new
    MyContainer[Orange](new Orange()) //Bad!
Covariance
class MyContainer[+A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents = manifest.erasure.getSimpleName
}

class NavelOrange extends Orange

val navelOrangeBasket: MyContainer[NavelOrange] =
    new MyContainer[Orange](new Orange()) //Bad!

val tangeloBasket: MyContainer[Tangelo] = new
    MyContainer[Orange](new Orange()) //Bad!
Covariance
class MyContainer[+A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents = manifest.erasure.getSimpleName
}

class NavelOrange extends Orange

val navelOrangeBasket: MyContainer[NavelOrange] =
    new MyContainer[Orange](new Orange()) //Bad!

val tangeloBasket: MyContainer[Tangelo] = new
    MyContainer[Orange](new Orange()) //Bad!
Covariance Explained
      trait Fruit

      abstract class Citrus extends Fruit

      class Orange extends Citrus

      class Tangelo extends Citrus

      class Apple extends Fruit

      class Banana extends Fruit

      class NavelOrange extends Orange
I have an Orange Basket, you have a Fruit Basket
Contravariance
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.contents // Citrus
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.contents // Citrus
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

*There is something missing

 *No Return Values
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.contents // Citrus
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

val orangeBasket: MyContainer[Orange] = new
                  MyContainer[Citrus](new Tangelo)
orangeBasket.contents // Citrus
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

val tangeloBasket: MyContainer[Tangelo] = new
                   MyContainer[Citrus](new Orange)
tangeloBasket.contents // Citrus
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer[Orange](new Orange())
type mismatch;
[error] found   : MyContainer[Orange]
[error] required: MyContainer[Fruit]
Contravariance
class MyContainer[-A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def contents = manifest.erasure.getSimpleName
}

val fruitBasket: MyContainer[Fruit] = new
                 MyContainer(new Orange())
*This is ok! Why?
Contravariance Explained
        trait Fruit

        abstract class Citrus extends Fruit

        class Orange extends Citrus

        class Tangelo extends Citrus

        class Apple extends Fruit

        class Banana extends Fruit

        class NavelOrange extends Orange
I have an Orange Basket, you have a NavelOrange Basket
Invariance Revisited
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def get = item
  def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)

citrusBasket.set(new Orange)
citrusBasket.contents // Citrus

citrusBasket.set(new Tangelo)
citrusBasket.contents // Citrus
Invariance Revisited
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def get = item
  def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)

citrusBasket.set(new Orange)
citrusBasket.contents // Citrus

citrusBasket.set(new Tangelo)
citrusBasket.contents // Citrus
Invariance Revisited
class MyContainer[A](a: A)
                     (implicit manifest:
                      scala.reflect.Manifest[A]) {
  private[this] var item = a
  def set(a: A) {item = a}
  def get = item
  def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)

citrusBasket.set(new Orange)
citrusBasket.contents // Citrus

citrusBasket.set(new Tangelo)
citrusBasket.contents // Citrus
Real Life Scala Funk
abstract class Funny[+A, +B] {
       def foo(a:A):B
}
[error] covariant type A occurs in contravariant
        position in type A of value a
[error]        def foo(a:A):B
[error]                ^
[error] one error found
*Method Parameter is in the contravariant position
*Return Value is in the covariant position
Real Life Scala Funk (Fixed)
abstract class Funny[-A, +B] {
       def foo(a:A):B
}

Mind Trick: - goes in ; + goes out
Function1

package scala
trait Function1[-T1, +R] extends
     java.lang.Object with scala.ScalaObject {
  def $init$() : Unit
  def apply(v1 : T1) : R
  def compose[A](g : Function1[A, T1]) :
                Function1[A, R]
  def andThen[A](g : Function1[R, A]) :
                Function1[T1, A]
  override def toString()
}
Type Bounds
●   Constrain what can be used in a class
●   Constrain what can be used in a type
●   They are orthogonal to type variance
●   Scala Only
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.set(new Orange)
citrusBasket.contents // Citrus
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.set(new Orange)
citrusBasket.contents // Citrus
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.set(new Orange)
citrusBasket.contents // Citrus
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.set(new Orange)
citrusBasket.contents // Citrus
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.set(new Orange)
citrusBasket.contents // Citrus

citrusBasket.set(new Tangelo)
citrusBasket.contents // Citrus
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}

new MyContainer(new Orange) //OK
Upper Bound
class MyContainer[A <: Citrus](a: A)
                      (implicit manifest:
                       scala.reflect.Manifest[A]) {
   private[this] var item = a
   def set(a: A) {item = a}
   def get = item
   def contents = manifest.erasure.getSimpleName
}

new MyContainer(new Orange) //OK
new MyContainer[Fruit](new Orange)
type arguments [Fruit] do not conform to class
MyContainer's type parameter bounds [A <: Citrus]
Covariance Type Param with
           Upper Bound
class MyContainer[+A <: Citrus](a: A)
      (implicit manifest:
       scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents =
           manifest.erasure.getSimpleName
}
Covariance Type Param with
           Upper Bound
class MyContainer[+A <: Citrus](a: A)
      (implicit manifest:
       scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents =
           manifest.erasure.getSimpleName
}
Covariance Type Param with
           Upper Bound
class MyContainer[+A <: Citrus](a: A)
      (implicit manifest:
       scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents =
           manifest.erasure.getSimpleName
}

val citrusBasket: MyContainer[Citrus] = new
                  MyContainer[Citrus](new Orange)
citrusBasket.contents // Citrus

val citrusBasket2: MyContainer[Citrus] = new
                   MyContainer(new Tangelo)
citrusBasket2.contents // Citrus
Covariance Type Param with
           Upper Bound
class MyContainer[+A <: Citrus](a: A)
      (implicit manifest:
       scala.reflect.Manifest[A]) {
      private[this] val item = a
      def get = item
      def contents =
           manifest.erasure.getSimpleName
}

val citrusBasket6: MyContainer[Fruit] = new
                   MyContainer(new Orange)

type arguments [Fruit] do not conform to class
MyContainer's type parameter bounds [+A <: Citrus]
Contravariance Type Param with
         Upper Bound
class MyContainer[-A <: Citrus](a: A)(implicit
manifest: scala.reflect.Manifest[A]) {
      private[this] var item = a
      def set(a: A) {item = a}
      def contents =
          manifest.erasure.getSimpleName
}
Contravariance Type Param with
         Upper Bound
class MyContainer[-A <: Citrus](a: A)(implicit
manifest: scala.reflect.Manifest[A]) {
      private[this] var item = a
      def set(a: A) {item = a}
      def contents =
          manifest.erasure.getSimpleName
}

val citrusBasket1: MyContainer[Citrus] = new
                   MyContainer(new Tangelo)
citrusBasket1.contents // Citrus

val citrusBasket2 = new MyContainer(new Tangelo)
citrusBasket2.contents // Tangelo
Contravariance Type Param with
         Upper Bound
class MyContainer[-A <: Citrus](a: A)(implicit
manifest: scala.reflect.Manifest[A]) {
      private[this] var item = a
      def set(a: A) {item = a}
      def contents =
          manifest.erasure.getSimpleName
}

val citrusBasket1: MyContainer[Citrus] = new
                   MyContainer(new Tangelo)
citrusBasket1.contents // Citrus

val citrusBasket2 = new MyContainer(new Tangelo)
citrusBasket2.contents // Tangelo

val citrusBasket3 = new MyContainer(new Orange)
citrusBasket3.contents // Orange
Contravariance Type Param with
         Upper Bound
class MyContainer[-A <: Citrus](a: A)(implicit
manifest: scala.reflect.Manifest[A]) {
      private[this] var item = a
      def set(a: A) {item = a}
      def contents =
          manifest.erasure.getSimpleName
}

val citrusBasket6 = new MyContainer(new Apple)

val citrusBasket7 = new MyContainer(new
                    Orange():Fruit)

val citrusBasket8:MyContainer[Fruit] = new
                  MyContainer(new Orange())
inferred type arguments do not conform to class
MyContainer's type parameter bounds [-A <:
AboutTypeBounds.this.Citrus]
Contravariance Type Param with
 both Upper and Lower Bounds
class MyContainer[-A >: Citrus <: AnyRef](a: A)
      (implicit manifest: scala.reflect.Manifest[A]) {

    private[this] var item = a

    def set(a: A) {item = a}

    def contents = manifest.erasure.getSimpleName
}
Contravariance Type Param with
 both Upper and Lower Bounds
class MyContainer[-A >: Citrus <: AnyRef](a: A)
      (implicit manifest: scala.reflect.Manifest[A]) {

    private[this] var item = a

    def set(a: A) {item = a}

    def contents = manifest.erasure.getSimpleName
}
Contravariance Type Param with
 both Upper and Lower Bounds
class MyContainer[-A >: Citrus <: AnyRef](a: A)
      (implicit manifest: scala.reflect.Manifest[A]) {

    private[this] var item = a

    def set(a: A) {item = a}

    def contents = manifest.erasure.getSimpleName
}
Too many permutations, but just
         a reminder...
●   Type Variances have little to do with Type
    Bounds.
●   The left hand type must be undefined, the
    other's defined.
●   Scala will coerce and infer types for you.
View Bounds
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T] (x: T, y: T)(implicit v: T => JBigInt)   =
                        v(y).add(v(x))

add(3, 5) // BigInteger(15)
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T] (x: T, y: T)(implicit v: T => JBigInt)   =
                        v(y).add(v(x))

add(3, 5) // BigInteger(15)
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T] (x: T, y: T)(implicit v: T => JBigInt)   =
                        v(y).add(v(x))

add(3, 5) // BigInteger(15)
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T] (x: T, y: T)(implicit v: T => JBigInt)   =
                        v(y).add(v(x))

add(3, 5) // BigInteger(15)
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T] (x: T, y: T)(implicit v: T => JBigInt)   =
                        v(y).add(v(x))

add(3, 5) // BigInteger(15)
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T] (x: T, y: T)(implicit v: T => JBigInt)   =
                        y.add(x)

add(3, 5) // BigInteger(15)
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T <% JBigInt] (x: T, y: T) = y.add(x)

add(3, 5) // BigInteger(15)
View Bounds
import java.math.{BigInteger => JBigInt}

implicit def Int2BigIntegerConvert(value: Int) =
             new JBigInt(value.toString)

def add[T <% JBigInt] (x: T, y: T) = y.add(x)

add(3, 5) // BigInteger(15)
Partially Applied Functions vs.
       Partial Functions
Partially Applied Function

def sum(a: Int, b: Int, c: Int) = a + b + c
val sum3 = sum _
sum3(1, 9, 7) // 17
sum(4, 5, 6) // 15
Partially Applied Function

def sum(a: Int, b: Int, c: Int) = a + b + c
val sum3 = sum _
sum3(1, 9, 7) // 17
sum(4, 5, 6) // 15
Partially Applied Function

def sum(a: Int, b: Int, c: Int) = a + b + c
val sum3 = sum _
sum3(1, 9, 7) // 17
sum(4, 5, 6) // 15

def sum(a: Int, b: Int, c: Int) = a + b + c
val sumC = sum(1, 10, _:Int) //not a cast
sumC(4) // 15
sum(4, 5, 6) // 15
Partially Applied Function

def sum(a: Int, b: Int, c: Int) = a + b + c
val sum3 = sum _
sum3(1, 9, 7) // 17
sum(4, 5, 6) // 15

def sum(a: Int, b: Int, c: Int) = a + b + c
val sumC = sum(1, 10, _:Int) //not a cast
sumC(4) // 15
sum(4, 5, 6) // 15
Partially Applied Function

def sum(a: Int, b: Int, c: Int) = a + b + c
val sum3 = sum _
sum3(1, 9, 7) // 17
sum(4, 5, 6) // 15

def sum(a: Int, b: Int, c: Int) = a + b + c
val sumC = sum(1, 10, _:Int) //not a cast
sumC(4) // 15
sum(4, 5, 6) // 15
Partially Applied Function

def sum(a: Int, b: Int, c: Int) = a + b + c
val sum3 = sum _
sum3(1, 9, 7) // 17
sum(4, 5, 6) // 15

def sum(a: Int, b: Int, c: Int) = a + b + c
val sumC = sum(1, 10, _:Int) //not a cast
sumC(4) // 15
sum(4, 5, 6) // 15
Partial Functions
Partial Functions
●   Performs an function
●   If Criteria is met
Partial Functions
val doubleEvens: PartialFunction[Int, Int] =
      new PartialFunction[Int, Int] {

    def isDefinedAt(x: Int) = x % 2 == 0

    def apply(v1: Int) = v1 * 2
}
Partial Functions
val doubleEvens: PartialFunction[Int, Int] =
      new PartialFunction[Int, Int] {

    def isDefinedAt(x: Int) = x % 2 == 0

    def apply(v1: Int) = v1 * 2
}
Partial Functions
val doubleEvens: PartialFunction[Int, Int] =
      new PartialFunction[Int, Int] {

    def isDefinedAt(x: Int) = x % 2 == 0

    def apply(v1: Int) = v1 * 2
}
Partial Functions
val doubleEvens: PartialFunction[Int, Int] =
      new PartialFunction[Int, Int] {

    def isDefinedAt(x: Int) = x % 2 == 0

    def apply(v1: Int) = v1 * 2
}

val tripleOdds: PartialFunction[Int, Int] =
       new PartialFunction[Int, Int] {

     def isDefinedAt(x: Int) = x % 2 != 0

     def apply(v1: Int) = v1 * 3
}
Partial Functions
val doubleEvens: PartialFunction[Int, Int] =
      new PartialFunction[Int, Int] {

    def isDefinedAt(x: Int) = x % 2 == 0

    def apply(v1: Int) = v1 * 2
}

val tripleOdds: PartialFunction[Int, Int] =
       new PartialFunction[Int, Int] {

     def isDefinedAt(x: Int) = x % 2 != 0

     def apply(v1: Int) = v1 * 3
}

val whatToDo = doubleEvens orElse tripleOdds
Partial Functions
val doubleEvens: PartialFunction[Int, Int] =
      new PartialFunction[Int, Int] {

    def isDefinedAt(x: Int) = x % 2 == 0

    def apply(v1: Int) = v1 * 2
}
val tripleOdds: PartialFunction[Int, Int] =
       new PartialFunction[Int, Int] {

     def isDefinedAt(x: Int) = x % 2 != 0

     def apply(v1: Int) = v1 * 3
}
val whatToDo = doubleEvens orElse tripleOdds

whatToDo(3) // 9
whatToDo(4) // 8
Partial Functions as case
            statements
val doubleEvens: PartialFunction[Int, Int] =
           new PartialFunction[Int, Int] {

    def isDefinedAt(x: Int) = x % 2 == 0

    def apply(v1: Int) = v1 * 2
}

Can become...

val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}
Partial Functions as case
         statements
val doubleEvens: PartialFunction[Int, Int] = {
  case x: Int if ((x % 2) == 0) => x * 2
}

val tripleOdds: PartialFunction[Int, Int] = {
  case x: Int if ((x % 2) != 0) => x * 3
}

val whatToDo = doubleEvens orElse tripleOdds

whatToDo(3) // 9
whatToDo(4) // 8
andThen More Partial Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}

val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}

val addFive = (x: Int) => x + 5

val whatToDo = doubleEvens orElse tripleOdds andThen addFive

whatToDo(3) // 14
whatToDo(4) // 13
andThen More Partial Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}

val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}

val addFive = (x: Int) => x + 5

val whatToDo = doubleEvens orElse tripleOdds andThen addFive

whatToDo(3) // 14
whatToDo(4) // 13
andThen More Partial Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}

val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}

val addFive = (x: Int) => x + 5

val whatToDo = doubleEvens orElse tripleOdds andThen addFive

whatToDo(3) // 14
whatToDo(4) // 13
andThen More Partial Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}

val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}

val addFive = (x: Int) => x + 5

val whatToDo = doubleEvens orElse tripleOdds andThen addFive

whatToDo(3) // 14
whatToDo(4) // 13
andThen More Partial Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}

val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}

val addFive = (x: Int) => x + 5

val whatToDo = doubleEvens orElse tripleOdds andThen addFive

whatToDo(3) // 14
whatToDo(4) // 13
andThen More Compound Partial
         Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}
val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}
val printEven: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) == 0) => "Even"
}
val printOdd: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) != 0) => "Odd"
}
val whatToDo = doubleEvens orElse tripleOdds andThen
               (printEven orElse printOdd)

whatToDo(3) // Odd
whatToDo(4) // Even
andThen More Compound Partial
         Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}
val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}
val printEven: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) == 0) => "Even"
}
val printOdd: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) != 0) => "Odd"
}
val whatToDo = doubleEvens orElse tripleOdds andThen
               (printEven orElse printOdd)

whatToDo(3) // Odd
whatToDo(4) // Even
andThen More Compound Partial
         Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}
val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}
val printEven: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) == 0) => "Even"
}
val printOdd: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) != 0) => "Odd"
}
val whatToDo = doubleEvens orElse tripleOdds andThen
               (printEven orElse printOdd)

whatToDo(3) // Odd
whatToDo(4) // Even
andThen More Compound Partial
         Functions
val doubleEvens: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) == 0) => x * 2
}
val tripleOdds: PartialFunction[Int, Int] = {
      case x: Int if ((x % 2) != 0) => x * 3
}
val printEven: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) == 0) => "Even"
}
val printOdd: PartialFunction[Int, String] = {
      case x: Int if ((x % 2) != 0) => "Odd"
}
val whatToDo = doubleEvens orElse tripleOdds andThen
               (printEven orElse printOdd)

whatToDo(3) should be("Odd")
whatToDo(4) should be("Even")
Overtime?
Context Bound
implicit val intList = List(1,2,3,4,5)
implicit val stringList =
                List("1", "2", "3", "4", "5")

def createCollectionBasedOnSample[A](a:A)
                    (implicit m:Manifest[A],
                             sample:List[A]) = {
    sample
}

createCollectionBasedOnSample(1).apply(0)
   //1
createCollectionBasedOnSample("Foo").apply(0)
  //"1"
Context Bound
implicit val intList = List(1,2,3,4,5)
implicit val stringList =
                List("1", "2", "3", "4", "5")

def createCollectionBasedOnSample[A](a:A)
                    (implicit m:Manifest[A],
                             sample:List[A]) = {
    sample
}

createCollectionBasedOnSample(1).apply(0)
   //1
createCollectionBasedOnSample("Foo").apply(0)
  //"1"
Context Bound
implicit val intList = List(1,2,3,4,5)
implicit val stringList =
                List("1", "2", "3", "4", "5")

def createCollectionBasedOnSample[A](a:A)
                    (implicit m:Manifest[A],
                             sample:List[A]) = {
    sample
}

createCollectionBasedOnSample(1).apply(0)
   //1
createCollectionBasedOnSample("Foo").apply(0)
  //"1"
Context Bound
implicit val intList = List(1,2,3,4,5)
implicit val stringList =
                List("1", "2", "3", "4", "5")

def createCollectionBasedOnSample[A](a:A)
                    (implicit m:Manifest[A],
                             sample:List[A]) = {
    sample
}

createCollectionBasedOnSample(1).apply(0)
   //1
createCollectionBasedOnSample("Foo").apply(0)
  //"1"
Context Bound
implicit val intList = List(1,2,3,4,5)
implicit val stringList =
      List("1", "2", "3", "4", "5")

def
    createCollectionBasedOnSample[A:Manifest:List]
       (a:A) = {
          implicitly[List[A]]
}

createCollectionBasedOnSample(2).apply(0) //1
createCollectionBasedOnSample(“Foo”).apply(0)
    //”1”
Context Bound
implicit val intList = List(1,2,3,4,5)
implicit val stringList =
      List("1", "2", "3", "4", "5")

def
    createCollectionBasedOnSample[A:Manifest:List]
       (a:A) = {
          implicitly[List[A]]
}

createCollectionBasedOnSample(2).apply(0) //1
createCollectionBasedOnSample(“Foo”).apply(0)
    //”1”
Context Bound
implicit val intList = List(1,2,3,4,5)
implicit val stringList =
      List("1", "2", "3", "4", "5")

def
    createCollectionBasedOnSample[A:Manifest:List]
       (a:A) = {
          implicitly[List[A]]
}

createCollectionBasedOnSample(2).apply(0) //1
createCollectionBasedOnSample(“Foo”).apply(0)
    //”1”
Generalized Type Constraints

     <:<    <%<     =:=
Generalized Type Constraints
class Pair[T](val first: T, val second: T) {
   def smaller = if (first < second) first
                 else second
}
Generalized Type Constraints
class Pair[T](val first: T, val second: T) {
   def smaller = if (first < second) first
                 else second
}

*This only works if type T is is Ordered[T]
Generalized Type Constraints
class Pair[T <: Ordered[T]]
          (val first: T, val second: T) {
   def smaller = if (first < second) first
                 else second
}
*Not all T is Ordered[T]
Generalized Type Constraints
class Pair[T]
          (val first: T, val second: T) {
   def smaller(implicit ev: T <:< Ordered[T]) =
       if (first < second) first else second
}
Generalized Type Constraints
class Pair[T]
          (val first: T, val second: T) {
   def smaller(implicit ev: T <:< Ordered[T]) =
       if (first < second) first else second
}
Conclusion
Thank you

Mais conteúdo relacionado

Semelhante a Scala Demystifying the Funky Stuff

Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kirill Rozov
 
Scala in a Java 8 World
Scala in a Java 8 WorldScala in a Java 8 World
Scala in a Java 8 WorldDaniel Blyth
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scaladjspiewak
 
ハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うbpstudy
 
Greach 2015 AST – Groovy Transformers: More than meets the eye!
Greach 2015   AST – Groovy Transformers: More than meets the eye!Greach 2015   AST – Groovy Transformers: More than meets the eye!
Greach 2015 AST – Groovy Transformers: More than meets the eye!Iván López Martín
 
Classes
ClassesClasses
ClassesSV.CO
 
Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. ExperienceMike Fogus
 
Scala - den smarta kusinen
Scala - den smarta kusinenScala - den smarta kusinen
Scala - den smarta kusinenRedpill Linpro
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 
Kotlin Programming Language. What it is all about. Roman Belov, PMM in Kotlin
Kotlin Programming Language. What it is all about. Roman Belov, PMM in KotlinKotlin Programming Language. What it is all about. Roman Belov, PMM in Kotlin
Kotlin Programming Language. What it is all about. Roman Belov, PMM in KotlinJetBrains Russia
 
Demystifying Type Class derivation with Shapeless
Demystifying Type Class derivation with ShapelessDemystifying Type Class derivation with Shapeless
Demystifying Type Class derivation with ShapelessYurii Ostapchuk
 
From android/java to swift (3)
From android/java to swift (3)From android/java to swift (3)
From android/java to swift (3)allanh0526
 

Semelhante a Scala Demystifying the Funky Stuff (17)

Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
 
Scala in a Java 8 World
Scala in a Java 8 WorldScala in a Java 8 World
Scala in a Java 8 World
 
High Wizardry in the Land of Scala
High Wizardry in the Land of ScalaHigh Wizardry in the Land of Scala
High Wizardry in the Land of Scala
 
Introduction kot iin
Introduction kot iinIntroduction kot iin
Introduction kot iin
 
ハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使うハイブリッド言語Scalaを使う
ハイブリッド言語Scalaを使う
 
Greach 2015 AST – Groovy Transformers: More than meets the eye!
Greach 2015   AST – Groovy Transformers: More than meets the eye!Greach 2015   AST – Groovy Transformers: More than meets the eye!
Greach 2015 AST – Groovy Transformers: More than meets the eye!
 
groovy & grails - lecture 3
groovy & grails - lecture 3groovy & grails - lecture 3
groovy & grails - lecture 3
 
Classes
ClassesClasses
Classes
 
Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. Experience
 
Scala - den smarta kusinen
Scala - den smarta kusinenScala - den smarta kusinen
Scala - den smarta kusinen
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
Kotlin Programming Language. What it is all about. Roman Belov, PMM in Kotlin
Kotlin Programming Language. What it is all about. Roman Belov, PMM in KotlinKotlin Programming Language. What it is all about. Roman Belov, PMM in Kotlin
Kotlin Programming Language. What it is all about. Roman Belov, PMM in Kotlin
 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
 
Demystifying Type Class derivation with Shapeless
Demystifying Type Class derivation with ShapelessDemystifying Type Class derivation with Shapeless
Demystifying Type Class derivation with Shapeless
 
Kotlin
KotlinKotlin
Kotlin
 
From android/java to swift (3)
From android/java to swift (3)From android/java to swift (3)
From android/java to swift (3)
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 

Último

Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Último (20)

Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

Scala Demystifying the Funky Stuff

  • 1. Scala: Demystifying The Funky Stuff Daniel Hinojosa Email: dhinojosa@evolutionnext.com Twitter: @dhinojosa Google+: gplus.to/dhinojosa
  • 2. The Goal “To make Scala less mysterious, less intimidating”
  • 4. Are you interested? ● Covers some of the harder Scala concepts ● Predef and package objects ● Types, Abstract Types & Type Projections ● implicit Parameters, Converters, Wrappers ● Manifests ● Type Variances and Bounds ● Other goodness
  • 6. Predef ● scala.Predef object ● Automatically available since scala package is automatically included. ● Contains commons type aliases, and implicits (to be discussed)
  • 7. Types, Abstract Types and Type Projections
  • 8. Types type Goober = Int val x:Goober = 3
  • 9. Types class Foo { class Bar {} } val foo = new Foo() val bar = new foo.Bar()
  • 10. Types class Foo { class Bar {} } val foo = new Foo() val bar = new foo.Bar() * As opposed to Java, Inner objects belong to the Outer Object not the outer class
  • 11. Types class Foo { class Bar {} } val foo = new Foo() val bar:Foo#Bar = new foo.Bar() val bar:foo.Bar = new foo.Bar()
  • 12. Types class Foo { class Bar {} } val foo = new Foo() val bar:Foo#Bar = new foo.Bar() val bar:foo.Bar = new foo.Bar()
  • 13. Types class Foo { class Bar {} } val foo = new Foo() val bar:Foo#Bar = new foo.Bar() val bar:foo.Bar = new foo.Bar()
  • 14. Types class Foo { class Bar {} } val foo = new Foo() val bar:Foo#Bar = new foo.Bar() val bar:foo.Bar = new foo.Bar()
  • 15. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } val favoriteDrink: SomeSingleton.type = SomeSingleton favoriteDrink.z // Grande Latte"
  • 16. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } val favoriteDrink: SomeSingleton.type = SomeSingleton favoriteDrink.z // Grande Latte"
  • 17. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } val favoriteDrink: SomeSingleton.type = SomeSingleton favoriteDrink.z // Grande Latte"
  • 18. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } val favoriteDrink: SomeSingleton.type = SomeSingleton favoriteDrink.z // Grande Latte"
  • 19. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } def drink(x:SomeSingleton.type) { x.z should be ("Grande Latte") } drink(SomeSingleton)
  • 20. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } def drink(x:SomeSingleton.type) { x.z should be ("Grande Latte") } drink(SomeSingleton)
  • 21. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } def drink(x:SomeSingleton.type) { x.z should be ("Grande Latte") } drink(SomeSingleton)
  • 22. Stable/Singleton Type object SomeSingleton { val z = "Grande Latte" } def drink(x:SomeSingleton.type) { x.z should be ("Grande Latte") } drink(SomeSingleton)
  • 23. Stable/Singleton Type case class Celebrity(firstName:String, lastName:String) val tomHanks = new Celebrity("Tom", "Hanks") val jodieFoster = new Celebrity("Jodie", "Foster") val tomHanksImposter = new Celebrity("Tom", "Hanks") def enterTomHanksHouse(x:tomHanks.type) {}
  • 24. Stable/Singleton Type class Celebrity(firstName:String, lastName:String) val tomHanks = new Celebrity("Tom", "Hanks") val jodieFoster = Celebrity("Jodie", "Foster") val tomHanksImposter = new Celebrity("Tom", "Hanks") def enterTomHanksHouse(x:tomHanks.type) {}
  • 25. Stable/Singleton Type class Celebrity(firstName:String, lastName:String) val tomHanks = new Celebrity("Tom", "Hanks") val jodieFoster = Celebrity("Jodie", "Foster") val tomHanksImposter = new Celebrity("Tom", "Hanks") def enterTomHanksHouse(x:tomHanks.type) {} enterTomHanksHouse(tomHanks) //OK
  • 26. Stable/Singleton Type class Celebrity(firstName:String, lastName:String) val tomHanks = new Celebrity("Tom", "Hanks") val jodieFoster = Celebrity("Jodie", "Foster") val tomHanksImposter = new Celebrity("Tom", "Hanks") def enterTomHanksHouse(x:tomHanks.type) {} enterTomHanksHouse(tomHanks) //OK enterTomHanksHouse(jodieFoster) //Wrong
  • 27. Stable/Singleton Type class Celebrity(firstName:String, lastName:String) val tomHanks = new Celebrity("Tom", "Hanks") val jodieFoster = Celebrity("Jodie", "Foster") val tomHanksImposter = new Celebrity("Tom", "Hanks") def enterTomHanksHouse(x:tomHanks.type) {} enterTomHanksHouse(tomHanks) //OK enterTomHanksHouse(jodieFoster) //Wrong enterTomHanksHouse(tomHanksImposter) //Wrong
  • 28. Abstract Types abstract class Generator { type F def generate: F } class StringGenerator extends Generator { type F = String def generate = "Scooters are fun" } new StringGenerator().generate // Scooters are fun
  • 29. Abstract Types abstract class Generator { type F def generate: F } class StringGenerator extends Generator { type F = String def generate = "Scooters are fun" } new StringGenerator().generate // Scooters are fun
  • 30. Abstract Types abstract class Generator { type F def generate: F } class StringGenerator extends Generator { type F = String def generate = "Scooters are fun" } new StringGenerator().generate // Scooters are fun
  • 31. Abstract Types abstract class Generator { type F def generate: F } class StringGenerator extends Generator { type F = String def generate = "Scooters are fun" } new StringGenerator().generate // Scooters are fun
  • 32. Abstract Types abstract class Generator { type F def generate: F } class StringGenerator extends Generator { type F = String def generate = "Scooters are fun" } val x = new StringGenerator() classOf[x.F] = class java.lang.String classOf[x.type#F] = class java.lang.String classOf[StringGenerator#F] = class java.lang.String
  • 33. Abstract Types abstract class Generator { type F def generate: F } class StringGenerator extends Generator { type F = String def generate = "Scooters are fun" } val x = new StringGenerator() classOf[x.F] = class java.lang.String classOf[x.type#F] = class java.lang.String classOf[StringGenerator#F] = class java.lang.String val w:x.F = “Oh yeah!” val x:x.type#F = “Rock and Roll”
  • 36. Infix Types case class Person(name: String) class Loves[A, B](val a: A, val b: B) def announceCouple (couple: Loves[Person, Person]) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(new Loves(romeo, juliet)) //Romeo is in love with Juliet")
  • 37. Infix Types case class Person(name: String) class Loves[A, B](val a: A, val b: B) def announceCouple (couple: Loves[Person, Person]) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(new Loves(romeo, juliet)) //Romeo is in love with Juliet")
  • 38. Infix Types case class Person(name: String) class Loves[A, B](val a: A, val b: B) def announceCouple (couple: Loves[Person, Person]) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(new Loves(romeo, juliet)) //Romeo is in love with Juliet")
  • 39. Infix Types case class Person(name: String) class Loves[A, B](val a: A, val b: B) def announceCouple (couple: Person Loves Person) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(new Loves(romeo, juliet)) //Romeo is in love with Juliet")
  • 40. Infix Types case class Person(name: String) class Loves[A, B](val a: A, val b: B) def announceCouple (couple: Person Loves Person) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(new Loves(romeo, juliet)) //Romeo is in love with Juliet *It would be nice to say “romeo loves juliet”
  • 41. Infix Types with Infix Operators case class Person(name: String) { def loves(person: Person) = new Loves(this, person) } class Loves[A, B](val a: A, val b: B) def announceCouple(couple: Person Loves Person) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(romeo loves juliet) //Romeo is in love with Juliet")
  • 42. Infix Types with Infix Operators case class Person(name: String) { def loves(person: Person) = new Loves(this, person) } class Loves[A, B](val a: A, val b: B) def announceCouple(couple: Person Loves Person) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(romeo loves juliet) //Romeo is in love with Juliet")
  • 43. Infix Types with Infix Operators case class Person(name: String) { def loves(person: Person) = new Loves(this, person) } class Loves[A, B](val a: A, val b: B) def announceCouple(couple: Person Loves Person) = { couple.a.name + " is in love with " + couple.b.name } val romeo = new Person("Romeo") val juliet = new Person("Juliet") announceCouple(romeo loves juliet) //Romeo is in loveyou can omitJuliet param methods *Scala is a loose syntax language, with the () for one
  • 46. implicit parameters def howMuchCanIMake_?(hours: Int)(implicit dollarsPerHour: BigDecimal) = dollarsPerHour * hours
  • 47. implicit parameters def howMuchCanIMake_?(hours: Int)(implicit dollarsPerHour: BigDecimal) = dollarsPerHour * hours
  • 48. implicit parameters def howMuchCanIMake_?(hours: Int)(implicit dollarsPerHour: BigDecimal) = dollarsPerHour * hours *last curried parameter
  • 49. implicit parameters def howMuchCanIMake_?(hours: Int)(implicit dollarsPerHour: BigDecimal) = dollarsPerHour * hours implicit var hourlyRate = BigDecimal(34.00) *implicit reference must be in scope to be satisfied
  • 50. implicit parameters def howMuchCanIMake_?(hours: Int)(implicit dollarsPerHour: BigDecimal) = dollarsPerHour * hours implicit var hourlyRate = BigDecimal(34.00) howMuchCanIMake_?(30) //1020.00
  • 51. implicit parameters def howMuchCanIMake_?(hours: Int)(implicit dollarsPerHour: BigDecimal) = dollarsPerHour * hours implicit var hourlyRate = BigDecimal(34.00) howMuchCanIMake_?(30) //1020.00 hourlyRate = BigDecimal(95.00) //reassigning
  • 52. implicit parameters def howMuchCanIMake_?(hours: Int)(implicit dollarsPerHour: BigDecimal) = dollarsPerHour * hours implicit var hourlyRate = BigDecimal(34.00) howMuchCanIMake_?(30) //1020.00 hourlyRate = BigDecimal(95.00) //reassigning howMuchCanIMake_?(95) //(9025.00)
  • 54. multiple implicit parameters def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName
  • 55. multiple implicit parameters def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName
  • 56. multiple implicit parameters def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName implicit var hourlyRate = BigDecimal(34.00) implicit val currencyName = "Dollars"
  • 57. multiple implicit parameters def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName implicit var hourlyRate = BigDecimal(34.00) implicit val currencyName = "Dollars" howMuchCanIMake_?(30) // "1020.0 Dollars"
  • 58. multiple implicit parameters def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName implicit var hourlyRate = BigDecimal(34.00) implicit val currencyName = "Dollars" howMuchCanIMake_?(30) // "1020.0 Dollars" hourlyRate = BigDecimal(95.00)
  • 59. multiple implicit parameters def howMuchCanIMake_?(hours: Int)(implicit amount: BigDecimal, currencyName: String) = (amount * hours).toString() + " " + currencyName implicit var hourlyRate = BigDecimal(34.00) implicit val currencyName = "Dollars" howMuchCanIMake_?(30) // "1020.0 Dollars" hourlyRate = BigDecimal(95.00) howMuchCanIMake_?(95) // "9025.0 Dollars"
  • 61. default arguments instead of implicit def howMuchCanIMake_?(hours: Int, amount: BigDecimal = 34, currencyName: String ="Dollars") = (amount * hours).toString() + " " + currencyName
  • 62. default arguments instead of implicit def howMuchCanIMake_?(hours: Int, amount: BigDecimal = 34, currencyName: String ="Dollars") = (amount * hours).toString() + " " + currencyName howMuchCanIMake_?(30) // 1020 Dollars
  • 63. default arguments instead of implicit def howMuchCanIMake_?(hours: Int, amount: BigDecimal = 34, currencyName: String ="Dollars") = (amount * hours).toString() + " " + currencyName howMuchCanIMake_?(30) // 1020 Dollars howMuchCanIMake_?(95, 95) // 9025 Dollars
  • 64. default arguments instead of implicit def howMuchCanIMake_?(hours: Int, amount: BigDecimal = 34, currencyName: String ="Dollars") = (amount * hours).toString() + " " + currencyName howMuchCanIMake_?(30) // 1020 Dollars howMuchCanIMake_?(95, 95) // 9025 Dollars howMuchCanIMake_?(currencyName="Yen", amount=925, hours = 29) // 26825 Yen
  • 65. implicit objects in implicit parameters
  • 66. implicit objects in implicit parameters case class Employee(firstName:String, lastName:String, salary:Float)
  • 67. implicit objects in implicit parameters case class Employee(firstName:String, lastName:String, salary:Float) implicit object CEO extends Employee("Charo", "Frostycorn", 499000.22f)
  • 68. implicit objects in implicit parameters case class Employee(firstName:String, lastName:String, salary:Float) implicit object CEO extends Employee("Charo", "Frostycorn", 499000.22f) def isEmployeePaidTooMuch_?(salary:Float)(implicit modelEmployee:Employee) = salary > modelEmployee.salary * Using floating point as currency used for demonstration purposes only.
  • 70. Monkey Patching in Ruby class Integer def squared self * self end end >> 4.squared => 16 Source: http://paulbarry.com/articles/2009/04/17/implicit-conversions-scalas-type-safe-answer-to-rubys-open-class
  • 71. Issues with Monkey Patching in Ruby ● Other imports can override the your patch, effectively making debugging difficult. ● There are other ways of achieving the same effect. http://bit.ly/RBid2D Source:http://www.rubyinside.com/the-end-of-monkeypatching-4570.html
  • 72. Mopping in Groovy class Integer def squared self * self end end >> 4.squared => 16
  • 74. implicit wrappers class MyIntWrapper(val original: Int) { def isOdd = original % 2 != 0 }
  • 75. implicit wrappers class MyIntWrapper(val original: Int) { def isOdd = original % 2 != 0 } implicit def int2MyIntWrapper(value: Int) = new IntWrapper(value)
  • 76. implicit wrappers class MyIntWrapper(val original: Int) { def isOdd = original % 2 != 0 } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value)
  • 77. implicit wrappers class MyIntWrapper(val original: Int) { def isOdd = original % 2 != 0 } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value)
  • 78. implicit wrappers class MyIntWrapper(val original: Int) { def isOdd = original % 2 != 0 } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value)
  • 79. implicit wrappers class MyIntWrapper(val original: Int) { def isOdd = original % 2 != 0 } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) * The implicit needs to be within the same scope it is to be used
  • 80. implicit wrappers class MyIntWrapper(val original: Int) { def isOdd = original % 2 != 0 } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) 19.isOdd // true 20.isOdd // false
  • 82. implicit converters import java.math.BigInteger implicit def int2BigIntegerConvert(value: Int) = new BigInteger(value.toString)
  • 83. implicit converters import java.math.BigInteger implicit def int2BigIntegerConvert(value: Int) = new BigInteger(value.toString)
  • 84. implicit converters import java.math.BigInteger implicit def int2BigIntegerConvert(value: Int) = new BigInteger(value.toString)
  • 85. implicit converters import java.math.BigInteger implicit def int2BigIntegerConvert(value: Int) = new BigInteger(value.toString)
  • 86. implicit converters import java.math.BigInteger implicit def int2BigIntegerConvert(value: Int) = new BigInteger(value.toString)
  • 87. implicit converters import java.math.BigInteger implicit def Int2BigIntegerConvert(value: Int) = new BigInteger(value.toString)
  • 88. implicit converters import java.math.BigInteger implicit def Int2BigIntegerConvert(value: Int) = new BigInteger(value.toString) def add(a: BigInteger, b: BigInteger) = a.add(b)
  • 89. implicit converters import java.math.BigInteger implicit def Int2BigIntegerConvert(value: Int) = new BigInteger(value.toString) def add(a: BigInteger, b: BigInteger) = a.add(b) add(3, 6) // new BigInteger("9"))
  • 90. implicit converters with functions import java.math.BigInteger implicit val int2BigIntegerConvert = (value: Int) => new BigInteger(value.toString) def add(a: BigInteger, b: BigInteger) = a.add(b) add(3, 6) // new BigInteger("9"))
  • 91. implicit converters with functions import java.math.BigInteger implicit val int2BigIntegerConvert = (value: Int) => new BigInteger(value.toString) def add(a: BigInteger, b: BigInteger) = a.add(b) add(3, 6) // new BigInteger("9"))
  • 92. Where do implicits come from other than declarations?
  • 93. Importing implicits object MyPredef { class MyIntWrapper(val original: Int) { def isOdd() = original % 2 != 0 def isEven() = !isOdd() } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) } import MyPredef._ 19.isOdd() // true 20.isOdd() // false
  • 94. Importing implicits object MyPredef { class MyIntWrapper(val original: Int) { def isOdd() = original % 2 != 0 def isEven() = !isOdd() } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) } import MyPredef._ 19.isOdd() // true 20.isOdd() // false
  • 95. Importing implicits object MyPredef { class MyIntWrapper(val original: Int) { def isOdd() = original % 2 != 0 def isEven() = !isOdd() } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) } import MyPredef._ 19.isOdd() // true 20.isOdd() // false
  • 96. Importing implicits object MyPredef { class MyIntWrapper(val original: Int) { def isOdd() = original % 2 != 0 def isEven() = !isOdd() } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) } import MyPredef._ 19.isOdd() // true 20.isOdd() // false
  • 97. Importing implicits object MyPredef { class MyIntWrapper(val original: Int) { def isOdd() = original % 2 != 0 def isEven() = !isOdd() } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) } import MyPredef._ 19.isOdd() // true 20.isOdd() // false
  • 98. Importing implicits object MyPredef { class MyIntWrapper(val original: Int) { def isOdd() = original % 2 != 0 def isEven() = !isOdd() } implicit def int2MyIntWrapper(value: Int) = new MyIntWrapper(value) } import MyPredef._ 19.isOdd() // true 20.isOdd() // false
  • 99. Companion implicits class StringNumbering(val s:String, val i:Int) { override def toString = s def + (other:StringNumbering) = other.i + i } object StringNumbering { implicit def fromInt(i:Int):StringNumbering = new StringNumbering("Unknown", I) implicit def fromSnToInt(sn:StringNumbering):Int = sn.i } val numberOne = new StringNumbering("One", 1) (numberOne + 3) // 4 (3 + numberOne) // 4
  • 100. Companion implicits class StringNumbering(val s:String, val i:Int) { override def toString = s def + (other:StringNumbering) = other.i + i } object StringNumbering { implicit def fromInt(i:Int):StringNumbering = new StringNumbering("Unknown", I) implicit def fromSnToInt(sn:StringNumbering):Int = sn.i } val numberOne = new StringNumbering("One", 1) (numberOne + 3) // 4 (3 + numberOne) // 4
  • 101. Companion implicits class StringNumbering(val s:String, val i:Int) { override def toString = s def + (other:StringNumbering) = other.i + i } object StringNumbering { implicit def fromInt(i:Int):StringNumbering = new StringNumbering("Unknown", I) implicit def fromSnToInt(sn:StringNumbering):Int = sn.i } val numberOne = new StringNumbering("One", 1) (numberOne + 3) // 4 (3 + numberOne) // 4
  • 102. Companion implicits class StringNumbering(val s:String, val i:Int) { override def toString = s def + (other:StringNumbering) = other.i + i } object StringNumbering { implicit def fromInt(i:Int):StringNumbering = new StringNumbering("Unknown", i) implicit def fromSnToInt(sn:StringNumbering):Int = sn.i } val numberOne = new StringNumbering("One", 1) (numberOne + 3) // 4 (3 + numberOne) // 4
  • 103. Companion implicits class StringNumbering(val s:String, val i:Int) { override def toString = s def + (other:StringNumbering) = other.i + i } object StringNumbering { implicit def fromInt(i:Int):StringNumbering = new StringNumbering("Unknown", I) implicit def fromSnToInt(sn:StringNumbering):Int = sn.i } val numberOne = new StringNumbering("One", 1) (numberOne + 3) // 4 (3 + numberOne) // 4
  • 104. package implicits package com.xyzcorp package object abcproject { implicit val preferredAppliance = new Appliance("Dryer", "Gas") } In file com/xyzcorp/project/package.scala package com.xyzcorp.abcproject; class Appliance(val name: String, val powerType: String) class SomeClass { def foo (implicit v:Appliance) { println(v.name) //Dryer } } In file com/xyzcorp/abcproject/SomeClass.scala
  • 105. package implicits package com.xyzcorp package object abcproject { implicit val preferredAppliance = new Appliance("Dryer", "Gas") } In file com/xyzcorp/project/package.scala package com.xyzcorp.abcproject; class Appliance(val name: String, val powerType: String) class SomeClass { def foo (implicit v:Appliance) { println(v.name) //Dryer } } In file com/xyzcorp/abcproject/SomeClass.scala
  • 106. package implicits package com.xyzcorp package object abcproject { implicit val preferredAppliance = new Appliance("Dryer", "Gas") } In file com/xyzcorp/project/package.scala package com.xyzcorp.abcproject; class Appliance(val name: String, val powerType: String) class SomeClass { def foo (implicit v:Appliance) { println(v.name) //Dryer } } In file com/xyzcorp/abcproject/SomeClass.scala
  • 107. package implicits package com.xyzcorp package object abcproject { implicit val preferredAppliance = new Appliance("Dryer", "Gas") } In file com/xyzcorp/project/package.scala package com.xyzcorp.abcproject; class Appliance(val name: String, val powerType: String) class SomeClass { def foo (implicit v:Appliance) { println(v.name) //Dryer } } In file com/xyzcorp/abcproject/SomeClass.scala
  • 109. implicitly[] ● Contained within Predef ● Returns the implicit object (includes functions) that is currently with scope at moment of request.
  • 116. Manifests def inspect[T](l: List[T]) (implicit manifest:Manifest[T]) = manifest.toString val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil inspect(list) // Int
  • 117. Manifests def inspect[T](l: List[T]) (implicit manifest:Manifest[T]) = manifest.toString val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil inspect(list) // Int
  • 118. Manifests def inspect[T](l: List[T]) (implicit manifest:Manifest[T]) = manifest.toString val list = 1 :: 2 :: 3 :: 4 :: 5 :: Nil inspect(list) // Int
  • 119. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]{ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 120. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]{ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 121. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]){ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 122. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]){ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 123. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]{ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 124. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]{ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 125. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]{ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 126. Manifests case class Monkey(name: String) class Barrel[T](implicit m:scala.reflect.Manifest[T]{ def +(t: T) = "1 %s has been added".format(m.erasure.getSimpleName) } val monkeyBarrel = new Barrel[Monkey] monkeyBarrel + new Monkey("Shotgun") // "1 Monkey has been added"
  • 129. The Setup trait Fruit abstract class Citrus extends Fruit class Orange extends Citrus class Tangelo extends Citrus class Apple extends Fruit class Banana extends Fruit class NavelOrange extends Fruit
  • 130. Simple Invariant Case class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer(new Orange()) fruitBasket.contents // Orange
  • 131. Simple Invariant Case class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer(new Orange()) fruitBasket.contents // Orange
  • 132. Simple Invariant Case class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer(new Orange()) fruitBasket.contents // Orange
  • 133. Simple Invariant Case class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer(new Orange()) fruitBasket.contents // Orange
  • 134. Explicitly Declaring Type class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer[Fruit] (new Orange()) //Explicit call fruitBasket.contents // Fruit - static type
  • 135. Explicitly Declaring Type class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer[Fruit] (new Orange()) //Explicit call fruitBasket.contents // Fruit - static type
  • 136. Explicitly Declaring Type Differently class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer(new Orange():Fruit) //Explicit call fruitBasket.contents // "Fruit" - static type
  • 137. Explicitly Declaring Type Differently class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket = new MyContainer(new Orange():Fruit) //Explicit call fruitBasket.contents // "Fruit" - static type
  • 138. Explicitly Type Coersion class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer(new Orange())//Coerced fruitBasket.contents // "Fruit"
  • 139. Explicitly Type Coersion class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer(new Orange())//Coerced fruitBasket.contents // "Fruit"
  • 140. Explicitly Type Coersion class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer(new Orange())//Coerced fruitBasket.contents // "Fruit" *Based on the expected type it fills it in with type inference
  • 141. Attempting Polymorphism class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket:MyContainer[Fruit] = new MyContainer[Orange](new Orange())
  • 142. Attempting Polymorphism class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def get = item def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket:MyContainer[Fruit] = new MyContainer[Orange](new Orange()) [error] type mismatch; [error] found : MyContainer[Orange] [error] required: MyContainer[Fruit]
  • 144. Covariance class MyContainer[+A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange()) fruitBasket.contents // Orange
  • 145. Covariance class MyContainer[+A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange()) fruitBasket.contents // Orange
  • 146. Covariance class MyContainer[+A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange()) fruitBasket.contents // Orange *There is something missing *No Method Parameters
  • 147. Covariance class MyContainer[+A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } class NavelOrange extends Orange val navelOrangeBasket: MyContainer[NavelOrange] = new MyContainer[Orange](new Orange()) //Bad! val tangeloBasket: MyContainer[Tangelo] = new MyContainer[Orange](new Orange()) //Bad!
  • 148. Covariance class MyContainer[+A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } class NavelOrange extends Orange val navelOrangeBasket: MyContainer[NavelOrange] = new MyContainer[Orange](new Orange()) //Bad! val tangeloBasket: MyContainer[Tangelo] = new MyContainer[Orange](new Orange()) //Bad!
  • 149. Covariance class MyContainer[+A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } class NavelOrange extends Orange val navelOrangeBasket: MyContainer[NavelOrange] = new MyContainer[Orange](new Orange()) //Bad! val tangeloBasket: MyContainer[Tangelo] = new MyContainer[Orange](new Orange()) //Bad!
  • 150. Covariance class MyContainer[+A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } class NavelOrange extends Orange val navelOrangeBasket: MyContainer[NavelOrange] = new MyContainer[Orange](new Orange()) //Bad! val tangeloBasket: MyContainer[Tangelo] = new MyContainer[Orange](new Orange()) //Bad!
  • 151. Covariance Explained trait Fruit abstract class Citrus extends Fruit class Orange extends Citrus class Tangelo extends Citrus class Apple extends Fruit class Banana extends Fruit class NavelOrange extends Orange I have an Orange Basket, you have a Fruit Basket
  • 153. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName }
  • 154. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName }
  • 155. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName }
  • 156. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.contents // Citrus
  • 157. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.contents // Citrus
  • 158. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } *There is something missing *No Return Values
  • 159. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.contents // Citrus
  • 160. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val orangeBasket: MyContainer[Orange] = new MyContainer[Citrus](new Tangelo) orangeBasket.contents // Citrus
  • 161. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val tangeloBasket: MyContainer[Tangelo] = new MyContainer[Citrus](new Orange) tangeloBasket.contents // Citrus
  • 162. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer[Orange](new Orange()) type mismatch; [error] found : MyContainer[Orange] [error] required: MyContainer[Fruit]
  • 163. Contravariance class MyContainer[-A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val fruitBasket: MyContainer[Fruit] = new MyContainer(new Orange()) *This is ok! Why?
  • 164. Contravariance Explained trait Fruit abstract class Citrus extends Fruit class Orange extends Citrus class Tangelo extends Citrus class Apple extends Fruit class Banana extends Fruit class NavelOrange extends Orange I have an Orange Basket, you have a NavelOrange Basket
  • 165. Invariance Revisited class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus citrusBasket.set(new Tangelo) citrusBasket.contents // Citrus
  • 166. Invariance Revisited class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus citrusBasket.set(new Tangelo) citrusBasket.contents // Citrus
  • 167. Invariance Revisited class MyContainer[A](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus citrusBasket.set(new Tangelo) citrusBasket.contents // Citrus
  • 168. Real Life Scala Funk abstract class Funny[+A, +B] { def foo(a:A):B } [error] covariant type A occurs in contravariant position in type A of value a [error] def foo(a:A):B [error] ^ [error] one error found *Method Parameter is in the contravariant position *Return Value is in the covariant position
  • 169. Real Life Scala Funk (Fixed) abstract class Funny[-A, +B] { def foo(a:A):B } Mind Trick: - goes in ; + goes out
  • 170. Function1 package scala trait Function1[-T1, +R] extends java.lang.Object with scala.ScalaObject { def $init$() : Unit def apply(v1 : T1) : R def compose[A](g : Function1[A, T1]) : Function1[A, R] def andThen[A](g : Function1[R, A]) : Function1[T1, A] override def toString() }
  • 171. Type Bounds ● Constrain what can be used in a class ● Constrain what can be used in a type ● They are orthogonal to type variance ● Scala Only
  • 172. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName }
  • 173. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName }
  • 174. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus
  • 175. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus
  • 176. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus
  • 177. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus
  • 178. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.set(new Orange) citrusBasket.contents // Citrus citrusBasket.set(new Tangelo) citrusBasket.contents // Citrus
  • 179. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } new MyContainer(new Orange) //OK
  • 180. Upper Bound class MyContainer[A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def get = item def contents = manifest.erasure.getSimpleName } new MyContainer(new Orange) //OK new MyContainer[Fruit](new Orange) type arguments [Fruit] do not conform to class MyContainer's type parameter bounds [A <: Citrus]
  • 181. Covariance Type Param with Upper Bound class MyContainer[+A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName }
  • 182. Covariance Type Param with Upper Bound class MyContainer[+A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName }
  • 183. Covariance Type Param with Upper Bound class MyContainer[+A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket: MyContainer[Citrus] = new MyContainer[Citrus](new Orange) citrusBasket.contents // Citrus val citrusBasket2: MyContainer[Citrus] = new MyContainer(new Tangelo) citrusBasket2.contents // Citrus
  • 184. Covariance Type Param with Upper Bound class MyContainer[+A <: Citrus](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] val item = a def get = item def contents = manifest.erasure.getSimpleName } val citrusBasket6: MyContainer[Fruit] = new MyContainer(new Orange) type arguments [Fruit] do not conform to class MyContainer's type parameter bounds [+A <: Citrus]
  • 185. Contravariance Type Param with Upper Bound class MyContainer[-A <: Citrus](a: A)(implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName }
  • 186. Contravariance Type Param with Upper Bound class MyContainer[-A <: Citrus](a: A)(implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val citrusBasket1: MyContainer[Citrus] = new MyContainer(new Tangelo) citrusBasket1.contents // Citrus val citrusBasket2 = new MyContainer(new Tangelo) citrusBasket2.contents // Tangelo
  • 187. Contravariance Type Param with Upper Bound class MyContainer[-A <: Citrus](a: A)(implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val citrusBasket1: MyContainer[Citrus] = new MyContainer(new Tangelo) citrusBasket1.contents // Citrus val citrusBasket2 = new MyContainer(new Tangelo) citrusBasket2.contents // Tangelo val citrusBasket3 = new MyContainer(new Orange) citrusBasket3.contents // Orange
  • 188. Contravariance Type Param with Upper Bound class MyContainer[-A <: Citrus](a: A)(implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName } val citrusBasket6 = new MyContainer(new Apple) val citrusBasket7 = new MyContainer(new Orange():Fruit) val citrusBasket8:MyContainer[Fruit] = new MyContainer(new Orange()) inferred type arguments do not conform to class MyContainer's type parameter bounds [-A <: AboutTypeBounds.this.Citrus]
  • 189. Contravariance Type Param with both Upper and Lower Bounds class MyContainer[-A >: Citrus <: AnyRef](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName }
  • 190. Contravariance Type Param with both Upper and Lower Bounds class MyContainer[-A >: Citrus <: AnyRef](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName }
  • 191. Contravariance Type Param with both Upper and Lower Bounds class MyContainer[-A >: Citrus <: AnyRef](a: A) (implicit manifest: scala.reflect.Manifest[A]) { private[this] var item = a def set(a: A) {item = a} def contents = manifest.erasure.getSimpleName }
  • 192. Too many permutations, but just a reminder... ● Type Variances have little to do with Type Bounds. ● The left hand type must be undefined, the other's defined. ● Scala will coerce and infer types for you.
  • 194. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T] (x: T, y: T)(implicit v: T => JBigInt) = v(y).add(v(x)) add(3, 5) // BigInteger(15)
  • 195. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T] (x: T, y: T)(implicit v: T => JBigInt) = v(y).add(v(x)) add(3, 5) // BigInteger(15)
  • 196. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T] (x: T, y: T)(implicit v: T => JBigInt) = v(y).add(v(x)) add(3, 5) // BigInteger(15)
  • 197. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T] (x: T, y: T)(implicit v: T => JBigInt) = v(y).add(v(x)) add(3, 5) // BigInteger(15)
  • 198. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T] (x: T, y: T)(implicit v: T => JBigInt) = v(y).add(v(x)) add(3, 5) // BigInteger(15)
  • 199. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T] (x: T, y: T)(implicit v: T => JBigInt) = y.add(x) add(3, 5) // BigInteger(15)
  • 200. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T <% JBigInt] (x: T, y: T) = y.add(x) add(3, 5) // BigInteger(15)
  • 201. View Bounds import java.math.{BigInteger => JBigInt} implicit def Int2BigIntegerConvert(value: Int) = new JBigInt(value.toString) def add[T <% JBigInt] (x: T, y: T) = y.add(x) add(3, 5) // BigInteger(15)
  • 202. Partially Applied Functions vs. Partial Functions
  • 203. Partially Applied Function def sum(a: Int, b: Int, c: Int) = a + b + c val sum3 = sum _ sum3(1, 9, 7) // 17 sum(4, 5, 6) // 15
  • 204. Partially Applied Function def sum(a: Int, b: Int, c: Int) = a + b + c val sum3 = sum _ sum3(1, 9, 7) // 17 sum(4, 5, 6) // 15
  • 205. Partially Applied Function def sum(a: Int, b: Int, c: Int) = a + b + c val sum3 = sum _ sum3(1, 9, 7) // 17 sum(4, 5, 6) // 15 def sum(a: Int, b: Int, c: Int) = a + b + c val sumC = sum(1, 10, _:Int) //not a cast sumC(4) // 15 sum(4, 5, 6) // 15
  • 206. Partially Applied Function def sum(a: Int, b: Int, c: Int) = a + b + c val sum3 = sum _ sum3(1, 9, 7) // 17 sum(4, 5, 6) // 15 def sum(a: Int, b: Int, c: Int) = a + b + c val sumC = sum(1, 10, _:Int) //not a cast sumC(4) // 15 sum(4, 5, 6) // 15
  • 207. Partially Applied Function def sum(a: Int, b: Int, c: Int) = a + b + c val sum3 = sum _ sum3(1, 9, 7) // 17 sum(4, 5, 6) // 15 def sum(a: Int, b: Int, c: Int) = a + b + c val sumC = sum(1, 10, _:Int) //not a cast sumC(4) // 15 sum(4, 5, 6) // 15
  • 208. Partially Applied Function def sum(a: Int, b: Int, c: Int) = a + b + c val sum3 = sum _ sum3(1, 9, 7) // 17 sum(4, 5, 6) // 15 def sum(a: Int, b: Int, c: Int) = a + b + c val sumC = sum(1, 10, _:Int) //not a cast sumC(4) // 15 sum(4, 5, 6) // 15
  • 210. Partial Functions ● Performs an function ● If Criteria is met
  • 211. Partial Functions val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 == 0 def apply(v1: Int) = v1 * 2 }
  • 212. Partial Functions val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 == 0 def apply(v1: Int) = v1 * 2 }
  • 213. Partial Functions val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 == 0 def apply(v1: Int) = v1 * 2 }
  • 214. Partial Functions val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 == 0 def apply(v1: Int) = v1 * 2 } val tripleOdds: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 != 0 def apply(v1: Int) = v1 * 3 }
  • 215. Partial Functions val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 == 0 def apply(v1: Int) = v1 * 2 } val tripleOdds: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 != 0 def apply(v1: Int) = v1 * 3 } val whatToDo = doubleEvens orElse tripleOdds
  • 216. Partial Functions val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 == 0 def apply(v1: Int) = v1 * 2 } val tripleOdds: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 != 0 def apply(v1: Int) = v1 * 3 } val whatToDo = doubleEvens orElse tripleOdds whatToDo(3) // 9 whatToDo(4) // 8
  • 217. Partial Functions as case statements val doubleEvens: PartialFunction[Int, Int] = new PartialFunction[Int, Int] { def isDefinedAt(x: Int) = x % 2 == 0 def apply(v1: Int) = v1 * 2 } Can become... val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 }
  • 218. Partial Functions as case statements val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val whatToDo = doubleEvens orElse tripleOdds whatToDo(3) // 9 whatToDo(4) // 8
  • 219. andThen More Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val addFive = (x: Int) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive whatToDo(3) // 14 whatToDo(4) // 13
  • 220. andThen More Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val addFive = (x: Int) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive whatToDo(3) // 14 whatToDo(4) // 13
  • 221. andThen More Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val addFive = (x: Int) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive whatToDo(3) // 14 whatToDo(4) // 13
  • 222. andThen More Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val addFive = (x: Int) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive whatToDo(3) // 14 whatToDo(4) // 13
  • 223. andThen More Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val addFive = (x: Int) => x + 5 val whatToDo = doubleEvens orElse tripleOdds andThen addFive whatToDo(3) // 14 whatToDo(4) // 13
  • 224. andThen More Compound Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val printEven: PartialFunction[Int, String] = { case x: Int if ((x % 2) == 0) => "Even" } val printOdd: PartialFunction[Int, String] = { case x: Int if ((x % 2) != 0) => "Odd" } val whatToDo = doubleEvens orElse tripleOdds andThen (printEven orElse printOdd) whatToDo(3) // Odd whatToDo(4) // Even
  • 225. andThen More Compound Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val printEven: PartialFunction[Int, String] = { case x: Int if ((x % 2) == 0) => "Even" } val printOdd: PartialFunction[Int, String] = { case x: Int if ((x % 2) != 0) => "Odd" } val whatToDo = doubleEvens orElse tripleOdds andThen (printEven orElse printOdd) whatToDo(3) // Odd whatToDo(4) // Even
  • 226. andThen More Compound Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val printEven: PartialFunction[Int, String] = { case x: Int if ((x % 2) == 0) => "Even" } val printOdd: PartialFunction[Int, String] = { case x: Int if ((x % 2) != 0) => "Odd" } val whatToDo = doubleEvens orElse tripleOdds andThen (printEven orElse printOdd) whatToDo(3) // Odd whatToDo(4) // Even
  • 227. andThen More Compound Partial Functions val doubleEvens: PartialFunction[Int, Int] = { case x: Int if ((x % 2) == 0) => x * 2 } val tripleOdds: PartialFunction[Int, Int] = { case x: Int if ((x % 2) != 0) => x * 3 } val printEven: PartialFunction[Int, String] = { case x: Int if ((x % 2) == 0) => "Even" } val printOdd: PartialFunction[Int, String] = { case x: Int if ((x % 2) != 0) => "Odd" } val whatToDo = doubleEvens orElse tripleOdds andThen (printEven orElse printOdd) whatToDo(3) should be("Odd") whatToDo(4) should be("Even")
  • 229. Context Bound implicit val intList = List(1,2,3,4,5) implicit val stringList = List("1", "2", "3", "4", "5") def createCollectionBasedOnSample[A](a:A) (implicit m:Manifest[A], sample:List[A]) = { sample } createCollectionBasedOnSample(1).apply(0) //1 createCollectionBasedOnSample("Foo").apply(0) //"1"
  • 230. Context Bound implicit val intList = List(1,2,3,4,5) implicit val stringList = List("1", "2", "3", "4", "5") def createCollectionBasedOnSample[A](a:A) (implicit m:Manifest[A], sample:List[A]) = { sample } createCollectionBasedOnSample(1).apply(0) //1 createCollectionBasedOnSample("Foo").apply(0) //"1"
  • 231. Context Bound implicit val intList = List(1,2,3,4,5) implicit val stringList = List("1", "2", "3", "4", "5") def createCollectionBasedOnSample[A](a:A) (implicit m:Manifest[A], sample:List[A]) = { sample } createCollectionBasedOnSample(1).apply(0) //1 createCollectionBasedOnSample("Foo").apply(0) //"1"
  • 232. Context Bound implicit val intList = List(1,2,3,4,5) implicit val stringList = List("1", "2", "3", "4", "5") def createCollectionBasedOnSample[A](a:A) (implicit m:Manifest[A], sample:List[A]) = { sample } createCollectionBasedOnSample(1).apply(0) //1 createCollectionBasedOnSample("Foo").apply(0) //"1"
  • 233. Context Bound implicit val intList = List(1,2,3,4,5) implicit val stringList = List("1", "2", "3", "4", "5") def createCollectionBasedOnSample[A:Manifest:List] (a:A) = { implicitly[List[A]] } createCollectionBasedOnSample(2).apply(0) //1 createCollectionBasedOnSample(“Foo”).apply(0) //”1”
  • 234. Context Bound implicit val intList = List(1,2,3,4,5) implicit val stringList = List("1", "2", "3", "4", "5") def createCollectionBasedOnSample[A:Manifest:List] (a:A) = { implicitly[List[A]] } createCollectionBasedOnSample(2).apply(0) //1 createCollectionBasedOnSample(“Foo”).apply(0) //”1”
  • 235. Context Bound implicit val intList = List(1,2,3,4,5) implicit val stringList = List("1", "2", "3", "4", "5") def createCollectionBasedOnSample[A:Manifest:List] (a:A) = { implicitly[List[A]] } createCollectionBasedOnSample(2).apply(0) //1 createCollectionBasedOnSample(“Foo”).apply(0) //”1”
  • 237. Generalized Type Constraints class Pair[T](val first: T, val second: T) { def smaller = if (first < second) first else second }
  • 238. Generalized Type Constraints class Pair[T](val first: T, val second: T) { def smaller = if (first < second) first else second } *This only works if type T is is Ordered[T]
  • 239. Generalized Type Constraints class Pair[T <: Ordered[T]] (val first: T, val second: T) { def smaller = if (first < second) first else second } *Not all T is Ordered[T]
  • 240. Generalized Type Constraints class Pair[T] (val first: T, val second: T) { def smaller(implicit ev: T <:< Ordered[T]) = if (first < second) first else second }
  • 241. Generalized Type Constraints class Pair[T] (val first: T, val second: T) { def smaller(implicit ev: T <:< Ordered[T]) = if (first < second) first else second }