### What?
- Use values without explicit reference
- OO: _is a_ + _has a_
- Implicits add: _is viewable as a_
- Loose Coupling, Tight Cohesion
Note:
- _is a_: extends: Cow is an Animal
- _has a_: members: Animal has a name
- Cow is viewable as a coat hanger
- Enables: Small core interfaces + rich views
Implicits enable you to use values without explicitly referencing them. This enables you to write less code, and let implicits do the heavy lifting for you. We will see how this can be useful.
If we look at Object Orientation, traditionally we see _is a_ and _has a_, respectively 'a Cow _is an_ Animal' and 'an Animal has a name' as field for example. Implicits enable _is viewable as a_ on top of this. This means we can convert values to other more rich values implicitly. 'a Cow _is viewable as a_ coat hanger'.This enables small and clean core interfaces and rich views on top of this, resulting in Loose Coupling, but Tight Cohesion.
### Examples
- Akka
```scala
trait ScalaActorRef
def !(message: Any)(implicit sender: ActorRef = Actor.noSender): Unit = ...
}```
```scala
actorRef ! SomeMessage("text")
```
- Futures
```scala
object Future {
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = ...
}```
```scala
Future {
doExpensiveComputation()
}
```
Note:
- implicit to pass in sender from actor context
- `ExectutionContext` to handle the thread management
Let's look at some examples.
In Akka when sending a message the tell (bang) is implemented with an implicit parameter `sender`. This enables us to send message to other actors without having to pass in itself in as the sender explicitly.
Another example is the implicit `ExecutionContext` when using `Future`s. `ExecutionContext` takes care of all the handing of the threads used by Futures under the hood. The implicit allows you to select a runtime for this once and use it implicitly for all the applicable `Future`s. The interface also allows you pass in another thread handling mechanism explicitly.
### Examples (2)
- Collections
```scala
trait TraversableOnce[+A] {
def sum[B >: A](implicit num: Numeric[B]): B = ...
}```
```scala
List(1,2,3).sum
res0: Int = 6
```
Note:
- `Numeric` type class to allow sum on things that can be added
It is also used in the Scala collections library. For example you can use `sum` on any `TraversableOnce` if there is an implicit available which makes sure we can do `plus` on the elements of the collection. This is an example of a type class.
### Examples (3)
- Finagle
```scala
@implicitNotFound("Builder is not fully configured: Cluster: ${HasCluster}, Codec: ${HasCodec},
HostConnectionLimit: ${HasHostConnectionLimit}")
private[builder] trait ClientConfigEvidence[HasCluster, HasCodec, HasHostConnectionLimit]
class ClientBuilder[Req, Rep, HasCluster, HasCodec, HasHostConnectionLimit] private[finagle](...) {
def build()(
implicit THE_BUILDER_IS_NOT_FULLY_SPECIFIED_SEE_ClientBuilder_DOCUMENTATION:
ClientConfigEvidence[HasCluster, HasCodec, HasHostConnectionLimit]
): Service[Req, Rep] = ...
}```
```scala
val builder: ClientBuilder[Request, Response, Yes, Yes, Nothing] =
ClientBuilder()
.codec(Http())
.hosts("twitter.com:80")
builder.build()
```
```
Error:(24, 15) Builder is not fully configured: Cluster: com.twitter.finagle.builder.ClientConfig.Yes,
Codec: com.twitter.finagle.builder.ClientConfig.Yes, HostConnectionLimit: Nothing
builder.build()
^```
Note:
- Builder only allows build() when all the configuration has been done
- `@implicitNotFound` custom error message when Implicit was not found.
This example is a bit more involved. Finagle provides a type safe builder class, which only builds if all the required settings are configured. The `build()` method can only be called when an implicit value is available which proofs that all settings are configured. If we construct a partially configured builder and try to `build()` it, we will get a compile time error. The annotation `@implicitNotFound` provides us with a custom error message when the implicit can not be found.
### Implicits enable
- DSLs
- Type evidence
- Reduce verbosity
- Type classes
- Dependency Injection at Compile time
- Extending libraries
Note:
- Some examples, but there is more
- DSLs: reuse standard Scala types and collections by extending them with your library functions
- Type evidence can help with creating more type safe interfaces, i.e. in Builders, constraint evidence
- Pass in dependencies depending on which implicit is in scope, used in Play & Slick
- Less writing, more implicit
I hope these examples have convinced you of the power of implicits. Implicits allow for a lot more. They can be used to extend types, including all the types in the standard library, allowing for powerful DSLs to be created embedded in the language.
They can provide type evidence as we saw in the Finagle builder and also in the `TraversableOnce.sum` example where a `Numeric[B]` had to be available.
They allow us to write less by leaving ceremony out, and thus reduce verbosity.
Implits enable us to create type classes in Scala, which add features for generic programming and extending of libraries.
We can do dependency injection by having different implicits in scope and this is all resolved at compile time.
And we can extend libraries or code that is out of our control.
### But beware
- Resolution rules can be difficult
- Automatic conversions
- Do not overuse
Note:
- Powerful, but can be magical in grasping, IDE support is really handy here
- Simple lexical examination not always enough
- Be careful with conversions, implicits can help, also when being explicit
+ Semantics can be different (`List` to `Stream` or `Double` to `Int`)
- If you do find yourself using implicits, always ask yourself if there is a way to achieve the same thing without their help. Principle of least power - Li Haoyi - which Martin referenced in the keynote
But take care. Implicits are a powerful extensions but being less explicit can become more magical. It is not always clear which method or field is being called just by looking at the code. Fortunately IDE's can help here.
Also, if values can be converted to values of other types, this can be triggered without you as developer even noticing and can result in doing to much work or possibly worse, automatic translations between types with different semantics, a List to a Stream for example.
If you can achieve your goal without implicits do not use them.
### Demo
- Implicit conversions (a.k.a. Implicit views)
```scala
implicit def a2B(a : A) : B = ...```
- Implicit parameters
```scala
def method(implicit x : Int) = ...```
- Implicit classes
```scala
implicit class X(y: Int)```
- Implicit declarations
```scala
implicit val x = ...```
Note:
- Explain how REPLesent works (`r` and `n`)
- `ImplicitParameter.sc`
- `ImplicitConversion.sc`
- `ImplicitClass.sc`
- Explain about IDE support
### Scoping
#### Odersky Explains
Lookup precedence:
1. By name only, without any prefix
2. In "implicit scope":
- companion/package object of
+ the source type
+ its parameters + supertype and supertraits
Note:
1. Visible as locals/members of enclosing classes and packages or as imports
2. companion objects that bear some relation to the type
- the importance is to be as general as possible without reverting to whole program analysis like Haskell does).
- This is so that library developers can provide sensible defaults in Companion Objects and Package Objects and users can override those by importing or defining implicits in local scope
### Demo
+ Scoping and resolving
Note:
- First show `scoping` package
- `Scoping.sc`
### Typeclass uses
- Ad-hoc polymorphism
- Extension of libraries
```
trait Numeric[T] extends Ordering[T] {
def plus(x: T, y: T): T
def minus(x: T, y: T): T
def times(x: T, y: T): T
...
}
```
Note:
- Term originates from Haskell, because no subtyping, to allow overloading of functions and operators
- Extending library without changing library code, loose coupling
+ Examples: Comparability, printability, summing
+ Type class captures common sets of operations
- Example sort a collection if elements of collection are comparable
+ Can be done by inheritance, interface etc
+ But, static and only when writing the element type
+ Basically extend the library
- Can be implemented in Scala using implicits
### Demo
Typeclass for JSON Serialisation
- Naive with subtyping
- Typeclass + improvements
Note:
- Adding JSonSerialisable everywhere will clutter your implemetation => High Coupling
- `typeclass/Naive.sc`
- `typeclass/JsonSerializer.sc`
## Implicits Inspected and Explained
Tim Soethout @ ScalaDays 2016 Berlin
http://blog.timmybankers.nl
### References
[Slides](http://blog.timmybankers.nl/implicits-inspected-and-explained-slides)
/
[Code](https://github.com/TimSoethout/implicits-inspected-and-explained-slides/tree/gh-pages/code)
- Scala documentation:
+ [Java Converters](http://docs.scala-lang.org/overviews/collections/conversions-between-java-and-scala-collections.html)
+ [Finding Implicits](http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html)
- Book: [Scala In Depth](https://www.manning.com/books/scala-in-depth)
- [Effective Scala](http://twitter.github.io/effectivescala/)
- Blog [All Things Runnable](http://lalitpant.blogspot.nl/2008/08/scala-implicits-dose-of-magic-part-1.html)
- [Scala Gitter channel](https://gitter.im/scala/scala), special thanks to @Ichoran and @som-snytt
- [REPLesent](https://github.com/marconilanna/REPLesent), for the demo slides