Skip to content

Commit 9b41cce

Browse files
committed
Rewrote implicit parameters tour
1 parent 7ab45eb commit 9b41cce

File tree

3 files changed

+83
-117
lines changed

3 files changed

+83
-117
lines changed

Diff for: tutorials/tour/_posts/2017-02-13-implicit-conversions.md

-59
This file was deleted.

Diff for: tutorials/tour/_posts/2017-02-13-implicit-parameters.md

-58
This file was deleted.

Diff for: tutorials/tour/_posts/2017-02-13-implicits.md

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
layout: tutorial
3+
title: Implicits
4+
5+
disqus: true
6+
7+
tutorial: scala-tour
8+
categories: tour
9+
num: 26
10+
next-page: implicit-conversions
11+
previous-page: explicitly-typed-self-references
12+
---
13+
Implicits allow for automatic application of code when an explicit application isn't supplied.
14+
15+
## Implicit parameters
16+
17+
Implicit parameters allow for the caller to omit an argument if an implicit one is in scope. Use the `implicit` keyword to make a value, object, or expression implicit. You also use it to make the parameter list implicit.
18+
```tut
19+
class Greeting(val greeting: String) {
20+
def greet(name: String) = s"$greeting, $name"
21+
}
22+
implicit val standardGreeting = new Greeting("Hello")
23+
24+
25+
def printGreeting(name: String)(implicit greeting: Greeting) = greeting.greet(name)
26+
27+
28+
printGreeting("Franchesca") // Hello, Franchesca
29+
printGreeting("Fred")(new Greeting("Good day")) // Good day, Fred
30+
```
31+
The `implicit val standardGreeting` is a value that can be supplied as an argument to an implicit parameter automatically. In the method `printGreeting`, the parameter `greeting` is implicit. This means that the caller can either supply an argument normally or skip it. With `greet("Franchesca")`, the compiler doesn't see a greeting but it notices that `greeting` is an implicit parameter so it searches the current scope for an implicit `Greeting` and finds `standardGreeting`.
32+
33+
This becomes useful when you have a lot of similar arguments to function calls throughout your program. However, implicits can make code more difficult to understand because it's not always obvious where they're defined if you import them from another module with a wildcard (e.g. `import MyPredef._`).
34+
35+
36+
37+
38+
## Implicit conversion
39+
40+
41+
An implicit conversion happens the type check fails for an argument and an implicit conversion is found.
42+
```
43+
def square(x: Double) = x * x
44+
val number: Int = 5
45+
square(number) // 25.0
46+
```
47+
This typecasting happens because of the method `implicit def int2double(x: Int): Double = x.toDouble` defined in `Predef` (a set of convenience methods in scope by default). When the compiler sees that `square` expects a `Double` but we pass an `Int`, it searches the scope for an `implicit` function that can do the conversion.
48+
49+
Implicits conversions can be useful when you're making a lot of calls to an API and the calls are verbose or require a type conversion. For example, if you want to create a button using Java swing, the code is verbose:
50+
```tut
51+
import java.awt.event.{ActionEvent, ActionListener}
52+
import javax.swing.JButton
53+
54+
val button = new JButton
55+
button.addActionListener(
56+
new ActionListener {
57+
def actionPerformed(event: ActionEvent) = {
58+
println("pressed!")
59+
}
60+
}
61+
)
62+
```
63+
You would need to write this same code for every button in order to _print "pressed" when the button is pressed_. You could instead abstract this away to an implicit conversion:
64+
```tut
65+
import java.awt.event.{ActionEvent, ActionListener}
66+
import javax.swing.JButton
67+
68+
implicit def function2ActionListener(f: ActionEvent => Unit) =
69+
new ActionListener {
70+
def actionPerformed(event: ActionEvent) = f(event)
71+
}
72+
73+
74+
val button = new JButton
75+
button.addActionListener(
76+
(_: ActionEvent) => println("pressed!")
77+
)
78+
```
79+
The implicit method `function2ActionListener` takes a function which accepts an ActionEvent. It then returns an `ActionListener` with the aforementioned function as its `actionPerformed`. Now when we call `button.addActionListener` (which accepts an `ActionListener`) with an anonymous function of type `ActionEvent => Unit`, the compiler looks for an implicit conversion function which can convert the type to `ActionListener`.
80+
81+
This removes a lot of the boilerplate because we can use an anonymous function. However, because implicits are often defined outside of the package, it can be difficult to debug. Therefore they are best used in libraries.
82+
83+
_Example Credit_: Odersky, Martin, Lex Spoon, and Bill Venners. Programming in Scala. Walnut Creek, CA: Artima, 2016.

0 commit comments

Comments
 (0)