Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

of

Scala Implicits - Not to be feared Slide 1 Scala Implicits - Not to be feared Slide 2 Scala Implicits - Not to be feared Slide 3 Scala Implicits - Not to be feared Slide 4 Scala Implicits - Not to be feared Slide 5 Scala Implicits - Not to be feared Slide 6 Scala Implicits - Not to be feared Slide 7 Scala Implicits - Not to be feared Slide 8 Scala Implicits - Not to be feared Slide 9 Scala Implicits - Not to be feared Slide 10 Scala Implicits - Not to be feared Slide 11 Scala Implicits - Not to be feared Slide 12 Scala Implicits - Not to be feared Slide 13 Scala Implicits - Not to be feared Slide 14 Scala Implicits - Not to be feared Slide 15 Scala Implicits - Not to be feared Slide 16 Scala Implicits - Not to be feared Slide 17 Scala Implicits - Not to be feared Slide 18 Scala Implicits - Not to be feared Slide 19 Scala Implicits - Not to be feared Slide 20 Scala Implicits - Not to be feared Slide 21 Scala Implicits - Not to be feared Slide 22 Scala Implicits - Not to be feared Slide 23 Scala Implicits - Not to be feared Slide 24 Scala Implicits - Not to be feared Slide 25 Scala Implicits - Not to be feared Slide 26 Scala Implicits - Not to be feared Slide 27 Scala Implicits - Not to be feared Slide 28 Scala Implicits - Not to be feared Slide 29 Scala Implicits - Not to be feared Slide 30 Scala Implicits - Not to be feared Slide 31 Scala Implicits - Not to be feared Slide 32 Scala Implicits - Not to be feared Slide 33 Scala Implicits - Not to be feared Slide 34 Scala Implicits - Not to be feared Slide 35 Scala Implicits - Not to be feared Slide 36 Scala Implicits - Not to be feared Slide 37 Scala Implicits - Not to be feared Slide 38 Scala Implicits - Not to be feared Slide 39 Scala Implicits - Not to be feared Slide 40 Scala Implicits - Not to be feared Slide 41 Scala Implicits - Not to be feared Slide 42 Scala Implicits - Not to be feared Slide 43 Scala Implicits - Not to be feared Slide 44 Scala Implicits - Not to be feared Slide 45 Scala Implicits - Not to be feared Slide 46 Scala Implicits - Not to be feared Slide 47 Scala Implicits - Not to be feared Slide 48 Scala Implicits - Not to be feared Slide 49 Scala Implicits - Not to be feared Slide 50 Scala Implicits - Not to be feared Slide 51 Scala Implicits - Not to be feared Slide 52 Scala Implicits - Not to be feared Slide 53 Scala Implicits - Not to be feared Slide 54 Scala Implicits - Not to be feared Slide 55 Scala Implicits - Not to be feared Slide 56 Scala Implicits - Not to be feared Slide 57 Scala Implicits - Not to be feared Slide 58 Scala Implicits - Not to be feared Slide 59 Scala Implicits - Not to be feared Slide 60 Scala Implicits - Not to be feared Slide 61 Scala Implicits - Not to be feared Slide 62 Scala Implicits - Not to be feared Slide 63 Scala Implicits - Not to be feared Slide 64 Scala Implicits - Not to be feared Slide 65 Scala Implicits - Not to be feared Slide 66 Scala Implicits - Not to be feared Slide 67 Scala Implicits - Not to be feared Slide 68 Scala Implicits - Not to be feared Slide 69 Scala Implicits - Not to be feared Slide 70 Scala Implicits - Not to be feared Slide 71 Scala Implicits - Not to be feared Slide 72 Scala Implicits - Not to be feared Slide 73 Scala Implicits - Not to be feared Slide 74
Upcoming SlideShare
Effective Scala (SoftShake 2013)
Next
Download to read offline and view in fullscreen.

46 Likes

Share

Download to read offline

Scala Implicits - Not to be feared

Download to read offline

These are the slides from a talk I gave at the Waterloo Scala Meetup on October 9th 2013. The talk was geared toward describing the purpose of implicits, use cases, and getting past that initial hump of "what are they and why would I need them" in order to get people to start exploring the ideas.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Scala Implicits - Not to be feared

  1. 1. Implicits Scalain Derek Wyatt Twitter: @derekwyatt Email: derek@derekwyatt.org Friday, 11 October, 13
  2. 2. Agenda Lies and Damn Lies Use Cases Scope ExampleCode! Truths Rules of Thumb Friday, 11 October, 13
  3. 3. Implicits are NEW Friday, 11 October, 13
  4. 4. Implicits are NEW New things can be cool! Friday, 11 October, 13
  5. 5. Implicits are NEW New things can be cool! New things can also be scary! ❉ Scala 2.10’s new set of warnings don’t help the situation. ❉ Friday, 11 October, 13
  6. 6. Implicits are NEW New things can be cool! New things can also be scary! ❉ Scala 2.10’s new set of warnings don’t help the situation. ❉ Especially when they’re complicated! Friday, 11 October, 13
  7. 7. Implicits are NEW New things can be cool! Newness + Complexness = Fearsometimes New things can also be scary! ❉ Scala 2.10’s new set of warnings don’t help the situation. ❉ Especially when they’re complicated! Friday, 11 October, 13
  8. 8. Implicits are NEW New things can be cool! Newness + Complexness = Fearsometimes Fear Avoidance New things can also be scary! ❉ Scala 2.10’s new set of warnings don’t help the situation. ❉ Especially when they’re complicated! Friday, 11 October, 13
  9. 9. Implicits are NEW New things can be cool! Newness + Complexness = Fearsometimes Fear Avoidance Avoidance :( New things can also be scary! ❉ Scala 2.10’s new set of warnings don’t help the situation. ❉ Especially when they’re complicated! Friday, 11 October, 13
  10. 10. Implicits Friday, 11 October, 13
  11. 11. Implicits Are Not Friday, 11 October, 13
  12. 12. Implicits Are Not Global variables LIE! Friday, 11 October, 13
  13. 13. Implicits Are Not Global variables Dynamically Applied LIE! DAMN LIE! Friday, 11 October, 13
  14. 14. Implicits Are Not Global variables Dynamically Applied Dangerous (...much...) LIE! DAMN LIE! Fib Friday, 11 October, 13
  15. 15. Implicits Are Not Global variables Dynamically Applied Dangerous (...much...) Implicits are like scissors. Use them. Don’t run with them. LIE! DAMN LIE! Fib Friday, 11 October, 13
  16. 16. Use Cases What are they used for? Friday, 11 October, 13
  17. 17. Use Case: Type Classes Friday, 11 October, 13
  18. 18. Use Case: Type Classes val a = someInt() val b = someOtherInt() val lesser = if (lessThan(a, b)) a else b Friday, 11 October, 13
  19. 19. Use Case: Type Classes val a = someInt() val b = someOtherInt() val lesser = if (lessThan(a, b)) a else b lessThan needsdefinition Friday, 11 October, 13
  20. 20. Use Case: Type Classes def lessThan[A](a: A, b: A)(implicit o: Ordering[A]): Boolean = o.lt(a, b) val a = someInt() val b = someOtherInt() val lesser = if (lessThan(a, b)) a else b lessThan needsdefinition Friday, 11 October, 13
  21. 21. Use Case: Type Classes def lessThan[A](a: A, b: A)(implicit o: Ordering[A]): Boolean = o.lt(a, b) val a = someInt() val b = someOtherInt() val lesser = if (lessThan(a, b)) a else b Ordering[Int]’s gottacome from somewhere lessThan needsdefinition Friday, 11 October, 13
  22. 22. Use Case: Type Classes def lessThan[A](a: A, b: A)(implicit o: Ordering[A]): Boolean = o.lt(a, b) implicit object intOrdering extends Ordering[Int] { def compare(a: Int, b: Int): Int = a - b } val a = someInt() val b = someOtherInt() val lesser = if (lessThan(a, b)) a else b Ordering[Int]’s gottacome from somewhere lessThan needsdefinition Friday, 11 October, 13
  23. 23. Use Case: Type Classes def lessThan[A](a: A, b: A)(implicit o: Ordering[A]): Boolean = o.lt(a, b) implicit object intOrdering extends Ordering[Int] { def compare(a: Int, b: Int): Int = a - b } val a = someInt() val b = someOtherInt() val lesser = if (lessThan(a, b)) a else b Ordering[Int]’s gottacome from somewhere val a = someInt() val b = someOtherInt() val lesser = if (lessThan(a, b)(intOrdering)) a else b lessThan needsdefinition Friday, 11 October, 13
  24. 24. Use Case: Class Extension Friday, 11 October, 13
  25. 25. Use Case: Class Extension val hexVals = “implicit”.asHexSeq // Vector(0x69, 0x6D, 0x70, 0x6C, 0x69, 0x63, 0x69, 0x74) The “Pimp” Friday, 11 October, 13
  26. 26. Use Case: Class Extension val hexVals = “implicit”.asHexSeq // Vector(0x69, 0x6D, 0x70, 0x6C, 0x69, 0x63, 0x69, 0x74) The “Pimp” implicit class HexableString(s: String) { def asHexSeq: Seq[String] = s map { c => f”0x$c%02X” } } The implicit class definition provides the extension method Friday, 11 October, 13
  27. 27. Use Case: Class Extension val hexVals = “implicit”.asHexSeq // Vector(0x69, 0x6D, 0x70, 0x6C, 0x69, 0x63, 0x69, 0x74) The “Pimp” implicit class HexableString(s: String) { def asHexSeq: Seq[String] = s map { c => f”0x$c%02X” } } The implicit class definition provides the extension method Bonus: If you extend implicit classes from AnyVal, no temporary object construction will occur. Friday, 11 October, 13
  28. 28. Use Case: Decluttering val future1 = someCall(“a parameter”, 5.seconds) val future2 = someCall(345, 5.seconds) val future3 = someCall(235.9352, 5.seconds) Friday, 11 October, 13
  29. 29. Use Case: Decluttering val future1 = someCall(“a parameter”, 5.seconds) val future2 = someCall(345, 5.seconds) val future3 = someCall(235.9352, 5.seconds) Blurgh Friday, 11 October, 13
  30. 30. Use Case: Decluttering val future1 = someCall(“a parameter”, 5.seconds) val future2 = someCall(345, 5.seconds) val future3 = someCall(235.9352, 5.seconds) Blurgh def someCall[A](a: A)(implicit timeout: Duration): Future[A] = ??? But, if we define someCall this way... Friday, 11 October, 13
  31. 31. Use Case: Decluttering val future1 = someCall(“a parameter”, 5.seconds) val future2 = someCall(345, 5.seconds) val future3 = someCall(235.9352, 5.seconds) Blurgh def someCall[A](a: A)(implicit timeout: Duration): Future[A] = ??? But, if we define someCall this way... implicit val myTimeoutValue = 5.seconds val future1 = someCall(“a parameter”) val future2 = someCall(345) val future3 = someCall(235.9352) And define an implicit value, we can simplify the calls... Friday, 11 October, 13
  32. 32. Use Case: Internal DSLs Create your own sub-language with ease Friday, 11 October, 13
  33. 33. Use Case: Internal DSLs Create your own sub-language with ease implicit class Recoverable[A](f: => A) { def recover(g: Throwable => A): A = try { f } catch { case t: Throwable => g(t) } } Friday, 11 October, 13
  34. 34. Use Case: Internal DSLs Create your own sub-language with ease implicit class Recoverable[A](f: => A) { def recover(g: Throwable => A): A = try { f } catch { case t: Throwable => g(t) } } def thisThrows(): Int = throw new Exception(“Argh!”) val stable = thisThrows() recover { t => if (t.getMessage == “Argh!”) 10 else 5 } // stable == 10 Friday, 11 October, 13
  35. 35. Use Case: Other stuff... Friday, 11 October, 13
  36. 36. Use Case: Other stuff... Overriding defaults def func[A](a: A)(implicit tout: Duration = 3.seconds): Future[A] Friday, 11 October, 13
  37. 37. Use Case: Other stuff... Overriding defaults def func[A](a: A)(implicit tout: Duration = 3.seconds): Future[A] Decoupled Dependency Injection class Database(ec: ExecutionContext) { def create(row: Row): Future[Result] = ??? def delete(id: RowId): Future[Result] = ??? // etc... } Friday, 11 October, 13
  38. 38. Use Case: Other stuff... Overriding defaults def func[A](a: A)(implicit tout: Duration = 3.seconds): Future[A] Decoupled Dependency Injection class Database(ec: ExecutionContext) { def create(row: Row): Future[Result] = ??? def delete(id: RowId): Future[Result] = ??? // etc... } NO! Friday, 11 October, 13
  39. 39. Use Case: Other stuff... Overriding defaults def func[A](a: A)(implicit tout: Duration = 3.seconds): Future[A] Decoupled Dependency Injection class Database { def create(row: Row)(implicit ec: ExecutionContext): Future[Result] def delete(id: RowId)(implicit ec: ExecutionContext): Future[Result] // etc... } We can now vary the ExecutionContext at any point by supplying the right implicit value Friday, 11 October, 13
  40. 40. Implicit Scope Rules!!!! Friday, 11 October, 13
  41. 41. Implicit Scope Rules!!!! There are a Lot of Rules Friday, 11 October, 13
  42. 42. Implicit Scope Rules!!!! There are a Lot of Rules Read “Scala In Depth”* *Josh Suereth Friday, 11 October, 13
  43. 43. Implicit Scope Rules!!!! There are a Lot of Rules Read “Scala In Depth”* Implicits without the Import Tax* *Josh Suereth Friday, 11 October, 13
  44. 44. Implicit Scope Rules!!!! There are a Lot of Rules Read “Scala In Depth”* Implicits without the Import Tax* *Josh Suereth I don’t know them super well, and I haven’t cut my arm off yet... Friday, 11 October, 13
  45. 45. Creating a Protocol Friday, 11 October, 13
  46. 46. Creating a Protocol an Implicit Friday, 11 October, 13
  47. 47. Creating a Protocol an Implicit We want: actor emit Message(“Hello”) Friday, 11 October, 13
  48. 48. Creating a Protocol an Implicit We want: actor emit Message(“Hello”) To Produce: actor ! Envelope(ComponentType(“Client”), ComponentType(“DBActor”), ComponentId(“/user/supervisor/DB”), WorkId(“764efa883dd7671c4a3bbd9e”), MsgType(“org.my.Message”), MsgNum(1), Message(“Hello”)) Friday, 11 October, 13
  49. 49. An Actor Derivation trait EnvelopingActor extends Actor with EnvelopeImplicits with ActorRefImplicits { implicit val myCompType = ComponentType(getClass.getSimpleName) implicit val myCompId = ComponentId(self.path) private var currentWorkId = unknownWorkId implicit def workId: WorkId = currentWorkId private var currentMsgNum = MsgNum(-1) implicit def msgNum: MsgNum = currentMsgNum def derivedReceive: Receive def derivedReceiveWrapper(wrapped: Receive): Receive = ??? final def receive = derivedReceiveWrapper(derivedReceive) } Friday, 11 October, 13
  50. 50. An Actor Derivation trait EnvelopingActor extends Actor with EnvelopeImplicits with ActorRefImplicits { implicit val myCompType = ComponentType(getClass.getSimpleName) implicit val myCompId = ComponentId(self.path) private var currentWorkId = unknownWorkId implicit def workId: WorkId = currentWorkId private var currentMsgNum = MsgNum(-1) implicit def msgNum: MsgNum = currentMsgNum def derivedReceive: Receive def derivedReceiveWrapper(wrapped: Receive): Receive = ??? final def receive = derivedReceiveWrapper(derivedReceive) } Sets up the implicits in a high priority scope Friday, 11 October, 13
  51. 51. The Receive Wrapper def derivedReceiveWrapper(wrapped: Receive): Receive = { case Envelope(_, _, _, workId, _, messageNum, message) => currentWorkIdVar = workId currentMessageNumVar = messageNum wrapped(message) case message => currentWorkIdVar = createWorkId() currentMessageNumVar = MessageNum(-1) wrapped(message) } Friday, 11 October, 13
  52. 52. The Receive Wrapper def derivedReceiveWrapper(wrapped: Receive): Receive = { case Envelope(_, _, _, workId, _, messageNum, message) => currentWorkIdVar = workId currentMessageNumVar = messageNum wrapped(message) case message => currentWorkIdVar = createWorkId() currentMessageNumVar = MessageNum(-1) wrapped(message) } Ensures that the values that vary (workId and msgNum) are updated in the implicit scope. Friday, 11 October, 13
  53. 53. Envelope Implicits trait EnvelopeImplicits { import scala.language.implicitConversions implicit def any2Envelope(a: Any) (implicit fromCompType: ComponentType, fromCompId: ComponentId, workId: WorkId, msgNum: MsgNum) = Envelope(fromCompType, fromCompId, unknownCompId, MsgType(a.getClass.getSimpleName), workId, msgNum, a) } Allows us to substitute a concrete Envelope value where an Any has been supplied. The implicit parameters make this possible. Friday, 11 October, 13
  54. 54. ActorRef Implicits trait ActorRefImplicits { implicit class PimpedActorRef(ref: ActorRef) { def emit(envelope: Envelope) (implicit sender: ActorRef = Actor.noSender): Unit = { ref.tell(envelope.copy( toComponentId = ComponentId(ref.path), msgNum = envelope.msgNum.increment ), sender) } } } The emit method demands an Envelope. When you call emit, that starts the implicit conversion! any2Envelope creates it, and we update it here with better values. Friday, 11 October, 13
  55. 55. Using the Protocol class MyActor extends EnvelopingActor { def derivedRecieve: Receive = { case Message(str) => someOtherActor emit Message(s”I got: $str”) } } Friday, 11 October, 13
  56. 56. Using the Protocol class MyActor extends EnvelopingActor { def derivedRecieve: Receive = { case Message(str) => someOtherActor emit Message(s”I got: $str”) } } Envelope( ComponentType(“SomeActor”), ComponentType(“MyActor”), ComponentId(“/user/myactor”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(0), Message(“SomeActor sent”)) Incoming Friday, 11 October, 13
  57. 57. Using the Protocol class MyActor extends EnvelopingActor { def derivedRecieve: Receive = { case Message(str) => someOtherActor emit Message(s”I got: $str”) } } Envelope( ComponentType(“SomeActor”), ComponentType(“MyActor”), ComponentId(“/user/myactor”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(0), Message(“SomeActor sent”)) Incoming Envelope( ComponentType(“MyActor”), ComponentType(“SomeOtherActor”), ComponentId(“/user/someother”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(1), Message(“I got: SomeActor sent”)) Outgoing Friday, 11 October, 13
  58. 58. Using the Protocol class MyActor extends EnvelopingActor { def derivedRecieve: Receive = { case Message(str) => someOtherActor emit Message(s”I got: $str”) } } Envelope( ComponentType(“SomeActor”), ComponentType(“MyActor”), ComponentId(“/user/myactor”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(0), Message(“SomeActor sent”)) Incoming Envelope( ComponentType(“MyActor”), ComponentType(“SomeOtherActor”), ComponentId(“/user/someother”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(1), Message(“I got: SomeActor sent”)) Outgoing Chained Friday, 11 October, 13
  59. 59. Using the Protocol class MyActor extends EnvelopingActor { def derivedRecieve: Receive = { case Message(str) => someOtherActor emit Message(s”I got: $str”) } } Envelope( ComponentType(“SomeActor”), ComponentType(“MyActor”), ComponentId(“/user/myactor”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(0), Message(“SomeActor sent”)) Incoming Envelope( ComponentType(“MyActor”), ComponentType(“SomeOtherActor”), ComponentId(“/user/someother”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(1), Message(“I got: SomeActor sent”)) Outgoing Maintained Friday, 11 October, 13
  60. 60. Using the Protocol class MyActor extends EnvelopingActor { def derivedRecieve: Receive = { case Message(str) => someOtherActor emit Message(s”I got: $str”) } } Envelope( ComponentType(“SomeActor”), ComponentType(“MyActor”), ComponentId(“/user/myactor”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(0), Message(“SomeActor sent”)) Incoming Envelope( ComponentType(“MyActor”), ComponentType(“SomeOtherActor”), ComponentId(“/user/someother”), WorkId(“ad7e877e41ff32a2”), MsgType(“org.my.Message”), MsgNum(1), Message(“I got: SomeActor sent”)) Outgoing Incremented Friday, 11 October, 13
  61. 61. All the Implicits Friday, 11 October, 13
  62. 62. All the Implicits Pimp ActorRef with Emit Friday, 11 October, 13
  63. 63. All the Implicits Pimp ActorRef with Emit Convert Any to envelope Friday, 11 October, 13
  64. 64. All the Implicits Pimp ActorRef with Emit Convert Any to envelope Simplify the API Friday, 11 October, 13
  65. 65. All the Implicits Pimp ActorRef with Emit Convert Any to envelope Simplify the API actor emit Message(”Here’s a message”) Just in case you forgot... Friday, 11 October, 13
  66. 66. All the Implicits Pimp ActorRef with Emit Convert Any to envelope Simplify the API actor emit Message(”Here’s a message”) Just in case you forgot... SIMPLE Friday, 11 October, 13
  67. 67. The Last Use Case Friday, 11 October, 13
  68. 68. The Last Use Case Implicits help you put complexity where it belongs... In your libraries! &Away from your Users! Friday, 11 October, 13
  69. 69. Pitfalls &Rules of Thumb Friday, 11 October, 13
  70. 70. Pitfalls &Rules of Thumb Use very specific types ComponentType(s: String) String()NOT Friday, 11 October, 13
  71. 71. Pitfalls &Rules of Thumb Use very specific types ComponentType(s: String) String()NOT Enable by import, not compiler switches Keeps libraries self-contained and avoids surprises Friday, 11 October, 13
  72. 72. Pitfalls &Rules of Thumb Use very specific types ComponentType(s: String) String()NOT Enable by import, not compiler switches Keeps libraries self-contained and avoids surprises Push parameters to methods if you can This keeps implicit resolution more flexible Friday, 11 October, 13
  73. 73. Pitfalls &Rules of Thumb Use very specific types ComponentType(s: String) String()NOT Enable by import, not compiler switches Keeps libraries self-contained and avoids surprises Push parameters to methods if you can This keeps implicit resolution more flexible Use the right tool for the right job!! Friday, 11 October, 13
  74. 74. Implicits Scalain Derek Wyatt Twitter: @derekwyatt Email: derek@derekwyatt.org Thanks to @heathermiller for the presentation style Source code is available at: https://github.com/primal-github/implicit-messaging Friday, 11 October, 13
  • vasu463

    Dec. 15, 2020
  • MichaelLi100

    Apr. 4, 2017
  • oustalar

    Mar. 29, 2017
  • capkidd

    Oct. 23, 2016
  • mgilgar

    Jul. 18, 2016
  • ranchunmao

    May. 13, 2016
  • Emaeyak

    Feb. 14, 2016
  • dxhuy88

    Nov. 9, 2015
  • anancds

    Aug. 12, 2015
  • DaewonJeong

    Jun. 28, 2015
  • YannOllivier2

    Jun. 10, 2015
  • aleff7

    May. 13, 2015
  • se77encc

    May. 8, 2015
  • seohoseok14

    May. 4, 2015
  • JungKim2

    May. 3, 2015
  • debop

    May. 3, 2015
  • pramod_sn

    Apr. 21, 2015
  • pricejosephd

    Nov. 2, 2014
  • mohanmca

    Aug. 31, 2014
  • fayimora

    Jul. 8, 2014

These are the slides from a talk I gave at the Waterloo Scala Meetup on October 9th 2013. The talk was geared toward describing the purpose of implicits, use cases, and getting past that initial hump of "what are they and why would I need them" in order to get people to start exploring the ideas.

Views

Total views

20,172

On Slideshare

0

From embeds

0

Number of embeds

4,778

Actions

Downloads

270

Shares

0

Comments

0

Likes

46

×