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

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 

Último (20)

Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 

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 }