Skip to content

Commit c810264

Browse files
benluobishabosha
andauthored
add code tabs in _overviews/scala3-book/num59 (#2640)
* add code tabs * Update _overviews/scala3-book/ca-given-using-clauses.md Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com> * Update _overviews/scala3-book/ca-given-using-clauses.md Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com> * Update _overviews/scala3-book/ca-given-using-clauses.md Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com> * Update _overviews/scala3-book/ca-given-using-clauses.md Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com> * Update _overviews/scala3-book/ca-given-using-clauses.md Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com> * Update _overviews/scala3-book/ca-given-using-clauses.md Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com> * add "Scala 3 Only" line as first line of the document. Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com>
1 parent edc0e0d commit c810264

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

_overviews/scala3-book/ca-given-using-clauses.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,24 @@ previous-page: ca-contextual-abstractions-intro
88
next-page: types-type-classes
99
---
1010

11+
12+
<h5>Use contextual abstraction <span class="tag tag-inline">Scala 3 Only</span></h5>
13+
1114
Scala 3 offers two important feature for contextual abstraction:
1215

1316
- **Using Clauses** allow you to specify parameters that, at the call site, can be omitted by the programmer and should be automatically provided by the context.
1417
- **Given Instances** let you define terms that can be used by the Scala compiler to fill in the missing arguments.
1518

1619
## Using Clauses
20+
1721
When designing a system, often context information like _configuration_ or settings need to be provided to the different components of your system.
1822
One common way to achieve this is by passing the configuration as additional argument to your methods.
1923

2024
In the following example, we define a case class `Config` to model some website configuration and pass it around in the different methods.
25+
26+
{% tabs nonusing %}
27+
{% tab 'Scala 2 and 3' %}
28+
2129
```scala
2230
case class Config(port: Int, baseUrl: String)
2331

@@ -29,11 +37,20 @@ def renderWidget(items: List[String], c: Config): String = ???
2937
val config = Config(8080, "docs.scala-lang.org")
3038
renderWebsite("/home", config)
3139
```
40+
41+
{% endtab %}
42+
{% endtabs %}
43+
3244
Let us assume that the configuration does not change throughout most of our code base.
3345
Passing `c` to each and every method call (like `renderWidget`) becomes very tedious and makes our program more difficult to read, since we need to ignore the `c` argument.
3446

3547
#### Using `using` to mark parameters as contextual
48+
3649
In Scala 3, we can mark some parameters of our methods as _contextual_.
50+
51+
{% tabs using1 %}
52+
{% tab 'Scala 3 Only' %}
53+
3754
```scala
3855
def renderWebsite(path: String)(using c: Config): String =
3956
"<html>" + renderWidget(List("cart")) + "</html>"
@@ -42,6 +59,10 @@ def renderWebsite(path: String)(using c: Config): String =
4259

4360
def renderWidget(items: List[String])(using c: Config): String = ???
4461
```
62+
63+
{% endtab %}
64+
{% endtabs %}
65+
4566
By starting a parameter section with the keyword `using`, we tell the Scala compiler that at the callsite it should automatically find an argument with the correct type.
4667
The Scala compiler thus performs **term inference**.
4768

@@ -50,30 +71,48 @@ So the program is equivalent to the one above.
5071

5172
In fact, since we do not need to refer to `c` in our implementation of `renderWebsite` anymore, we can even omit its name in the signature:
5273

74+
{% tabs using2 %}
75+
{% tab 'Scala 3 Only' %}
76+
5377
```scala
5478
// no need to come up with a parameter name
5579
// vvvvvvvvvvvvv
5680
def renderWebsite(path: String)(using Config): String =
5781
"<html>" + renderWidget(List("cart")) + "</html>"
5882
```
5983

84+
{% endtab %}
85+
{% endtabs %}
86+
6087
#### Explicitly providing contextual arguments
88+
6189
We have seen how to _abstract_ over contextual parameters and that the Scala compiler can provide arguments automatically for us.
6290
But how can we specify which configuration to use for our call to `renderWebsite`?
6391

6492
Like we specified our parameter section with `using`, we can also explicitly provide contextual arguments with `using:`
6593

94+
{% tabs using3 %}
95+
{% tab 'Scala 3 Only' %}
96+
6697
```scala
6798
renderWebsite("/home")(using config)
6899
```
100+
101+
{% endtab %}
102+
{% endtabs %}
103+
69104
Explicitly providing contextual parameters can be useful if we have multiple different values in scope that would make sense, and we want to make sure that the correct one is passed to the function.
70105

71106
For all other cases, as we will see in the next Section, there is also another way to bring contextual values into scope.
72107

73108
## Given Instances
109+
74110
We have seen that we can explicitly pass arguments as contextual parameters by marking the argument section of the _call_ with `using`.
75111
However, if there is _a single canonical value_ for a particular type, there is another preferred way to make it available to the Scala compiler: by marking it as `given`.
76112

113+
{% tabs given1 %}
114+
{% tab 'Scala 3 Only' %}
115+
77116
```scala
78117
val config = Config(8080, "docs.scala-lang.org")
79118
// this is the type that we want to provide the
@@ -84,15 +123,25 @@ given Config = config
84123
// this is the value the Scala compiler will infer
85124
// as argument to contextual parameters of type Config
86125
```
126+
127+
{% endtab %}
128+
{% endtabs %}
129+
87130
In the above example we specify that whenever a contextual parameter of type `Config` is omitted in the current scope, the compiler should infer `config` as an argument.
88131

89132
Having defined a given for `Config`, we can simply call `renderWebsite`:
90133

134+
{% tabs given2 %}
135+
{% tab 'Scala 3 Only' %}
136+
91137
```scala
92138
renderWebsite("/home")
93139
// ^^^^^
94140
// again no argument
95141
```
96142

143+
{% endtab %}
144+
{% endtabs %}
145+
97146
[reference]: {{ site.scala3ref }}/overview.html
98147
[blog-post]: /2020/11/06/explicit-term-inference-in-scala-3.html

0 commit comments

Comments
 (0)