Skip to content

Commit 05ad391

Browse files
authored
Merge pull request #2510 from benluo/why-scala-3-tabs-code
Why scala 3 tabs code
2 parents 29c2500 + 4a10fb1 commit 05ad391

File tree

2 files changed

+88
-25
lines changed

2 files changed

+88
-25
lines changed

_overviews/scala3-book/why-scala-3.md

+88-24
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ TODO: Is “Scala 3 Benefits” a better title?
1212
NOTE: Could mention “grammar” as a way of showing that Scala isn’t a large language; see this slide: https://www.slideshare.net/Odersky/preparing-for-scala-3#13
1313
{% endcomment %}
1414

15-
1615
There are many benefits to using Scala, and Scala 3 in particular.
1716
It’s hard to list every benefit of Scala, but a “Top Ten” list might look like this:
1817

@@ -27,8 +26,6 @@ It’s hard to list every benefit of Scala, but a “Top Ten” list might look
2726
9. The Scala ecosystem offers the most modern FP libraries in the world
2827
10. Strong type system
2928

30-
31-
3229
## 1) FP/OOP fusion
3330

3431
More than any other language, Scala supports a fusion of the FP and OOP paradigms.
@@ -40,15 +37,21 @@ As Martin Odersky has stated, the essence of Scala is a fusion of functional and
4037
Possibly some of the best examples of modularity are the classes in the standard library.
4138
For instance, a `List` is defined as a class---technically it’s an abstract class---and a new instance is created like this:
4239

40+
{% tabs list %}
41+
{% tab 'Scala 2 and 3' for=list %}
4342
```scala
4443
val x = List(1, 2, 3)
4544
```
45+
{% endtab %}
46+
{% endtabs %}
4647

4748
However, what appears to the programmer to be a simple `List` is actually built from a combination of several specialized types, including traits named `Iterable`, `Seq`, and `LinearSeq`.
4849
Those types are similarly composed of other small, modular units of code.
4950

5051
In addition to building a type like `List` from a series of modular traits, the `List` API also consists of dozens of other methods, many of which are higher-order functions:
5152

53+
{% tabs list-methods %}
54+
{% tab 'Scala 2 and 3' for=list-methods %}
5255
```scala
5356
val xs = List(1, 2, 3, 4, 5)
5457

@@ -57,41 +60,55 @@ xs.filter(_ < 3) // List(1, 2)
5760
xs.find(_ > 3) // Some(4)
5861
xs.takeWhile(_ < 3) // List(1, 2)
5962
```
63+
{% endtab %}
64+
{% endtabs %}
6065

6166
In those examples, the values in the list can’t be modified.
6267
The `List` class is immutable, so all of those methods return new values, as shown by the data in each comment.
6368

64-
65-
6669
## 2) A dynamic feel
6770

6871
Scala’s _type inference_ often makes the language feel dynamically typed, even though it’s statically typed.
6972
This is true with variable declaration:
7073

74+
{% tabs dynamic %}
75+
{% tab 'Scala 2 and 3' for=dynamic %}
7176
```scala
7277
val a = 1
7378
val b = "Hello, world"
7479
val c = List(1,2,3,4,5)
7580
val stuff = ("fish", 42, 1_234.5)
7681
```
82+
{% endtab %}
83+
{% endtabs %}
7784

7885
It’s also true when passing anonymous functions to higher-order functions:
7986

87+
{% tabs dynamic-hof %}
88+
{% tab 'Scala 2 and 3' for=dynamic-hof %}
8089
```scala
8190
list.filter(_ < 4)
8291
list.map(_ * 2)
8392
list.filter(_ < 4)
8493
.map(_ * 2)
8594
```
95+
{% endtab %}
96+
{% endtabs %}
8697

8798
and when defining methods:
8899

100+
{% tabs dynamic-method %}
101+
{% tab 'Scala 2 and 3' for=dynamic-method %}
89102
```scala
90103
def add(a: Int, b: Int) = a + b
91104
```
105+
{% endtab %}
106+
{% endtabs %}
92107

93108
This is more true than ever in Scala 3, such as when using [union types][union-types]:
94109

110+
{% tabs union %}
111+
{% tab 'Scala 3 Only' for=union %}
95112
```scala
96113
// union type parameter
97114
def help(id: Username | Password) =
@@ -103,21 +120,27 @@ def help(id: Username | Password) =
103120
// union type value
104121
val b: Password | Username = if (true) name else password
105122
```
106-
107-
123+
{% endtab %}
124+
{% endtabs %}
108125

109126
## 3) Concise syntax
110127

111128
Scala is a low ceremony, “concise but still readable” language. For instance, variable declaration is concise:
112129

130+
{% tabs concise %}
131+
{% tab 'Scala 2 and 3' for=concise %}
113132
```scala
114133
val a = 1
115134
val b = "Hello, world"
116135
val c = List(1,2,3)
117136
```
137+
{% endtab %}
138+
{% endtabs %}
118139

119140
Creating types like traits, classes, and enumerations are concise:
120141

142+
{% tabs enum %}
143+
{% tab 'Scala 3 Only' for=enum %}
121144
```scala
122145
trait Tail:
123146
def wagTail(): Unit
@@ -134,18 +157,23 @@ case class Person(
134157
age: Int
135158
)
136159
```
160+
{% endtab %}
161+
{% endtabs %}
137162

138163
Higher-order functions are concise:
139164

165+
{% tabs list-hof %}
166+
{% tab 'Scala 2 and 3' for=list-hof %}
167+
140168
```scala
141169
list.filter(_ < 4)
142170
list.map(_ * 2)
143171
```
172+
{% endtab %}
173+
{% endtabs %}
144174

145175
All of these expressions and many more are concise, and still very readable: what we call _expressive_.
146176

147-
148-
149177
## 4) Implicits, simplified
150178

151179
Implicits in Scala 2 were a major distinguishing design feature.
@@ -174,8 +202,6 @@ Benefits of these changes include:
174202

175203
These capabilities are described in detail in other sections, so see the [Contextual Abstraction introduction][contextual], and the section on [`given` and `using` clauses][given] for more details.
176204

177-
178-
179205
## 5) Seamless Java integration
180206

181207
Scala/Java interaction is seamless in many ways.
@@ -200,8 +226,6 @@ While almost every interaction is seamless, the [“Interacting with Java” cha
200226

201227
See that chapter for more details on these features.
202228

203-
204-
205229
## 6) Client &amp; server
206230

207231
Scala can be used on the server side with terrific frameworks:
@@ -214,8 +238,6 @@ The Scala.js ecosystem [has dozens of libraries](https://www.scala-js.org/librar
214238

215239
In addition to those tools, the [Scala Native](https://github.com/scala-native/scala-native) project “is an optimizing ahead-of-time compiler and lightweight managed runtime designed specifically for Scala.” It lets you build “systems” style binary executable applications with plain Scala code, and also lets you use lower-level primitives.
216240

217-
218-
219241
## 7) Standard library methods
220242

221243
You will rarely ever need to write a custom `for` loop again, because the dozens of pre-built functional methods in the Scala standard library will both save you time, and help make code more consistent across different applications.
@@ -225,6 +247,8 @@ While these all use the `List` class, the same methods work with other collectio
225247

226248
Here are some examples:
227249

250+
{% tabs list-more %}
251+
{% tab 'Scala 2 and 3' for=list-more %}
228252
```scala
229253
List.range(1, 3) // List(1, 2)
230254
List.range(start = 1, end = 6, step = 2) // List(1, 3, 5)
@@ -263,36 +287,50 @@ nums.sorted // List(1, 5, 7, 8, 10)
263287
nums.sortWith(_ < _) // List(1, 5, 7, 8, 10)
264288
nums.sortWith(_ > _) // List(10, 8, 7, 5, 1)
265289
```
266-
267-
290+
{% endtab %}
291+
{% endtabs %}
268292

269293
## 8) Built-in best practices
270294

271295
Scala idioms encourage best practices in many ways.
272296
For immutability, you’re encouraged to create immutable `val` declarations:
273297

298+
{% tabs val %}
299+
{% tab 'Scala 2 and 3' for=val %}
274300
```scala
275301
val a = 1 // immutable variable
276302
```
303+
{% endtab %}
304+
{% endtabs %}
277305

278306
You’re also encouraged to use immutable collections classes like `List` and `Map`:
279307

308+
{% tabs list-map %}
309+
{% tab 'Scala 2 and 3' for=list-map %}
280310
```scala
281311
val b = List(1,2,3) // List is immutable
282312
val c = Map(1 -> "one") // Map is immutable
283313
```
314+
{% endtab %}
315+
{% endtabs %}
284316

285317
Case classes are primarily intended for use in [domain modeling]({% link _overviews/scala3-book/domain-modeling-intro.md %}), and their parameters are immutable:
286318

319+
{% tabs case-class %}
320+
{% tab 'Scala 2 and 3' for=case-class %}
287321
```scala
288322
case class Person(name: String)
289323
val p = Person("Michael Scott")
290324
p.name // Michael Scott
291325
p.name = "Joe" // compiler error (reassignment to val name)
292326
```
327+
{% endtab %}
328+
{% endtabs %}
293329

294330
As shown in the previous section, Scala collections classes support higher-order functions, and you can pass methods (not shown) and anonymous functions into them:
295331

332+
{% tabs higher-order %}
333+
{% tab 'Scala 2 and 3' for=higher-order %}
296334
```scala
297335
a.dropWhile(_ < 25)
298336
a.filter(_ < 25)
@@ -301,25 +339,52 @@ a.filter(_ < 30).map(_ * 10)
301339
nums.sortWith(_ < _)
302340
nums.sortWith(_ > _)
303341
```
342+
{% endtab %}
343+
{% endtabs %}
304344

305345
`match` expressions let you use pattern matching, and they truly are _expressions_ that return values:
306346

347+
{% tabs match class=tabs-scala-version %}
348+
{% tab 'Scala 2' for=match %}
349+
```scala
350+
val numAsString = i match {
351+
case 1 | 3 | 5 | 7 | 9 => "odd"
352+
case 2 | 4 | 6 | 8 | 10 => "even"
353+
case _ => "too big"
354+
}
355+
```
356+
{% endtab %}
357+
358+
{% tab 'Scala 3' for=match %}
307359
```scala
308360
val numAsString = i match
309361
case 1 | 3 | 5 | 7 | 9 => "odd"
310362
case 2 | 4 | 6 | 8 | 10 => "even"
311363
case _ => "too big"
312364
```
365+
{% endtab %}
366+
{% endtabs %}
313367

314368
Because they can return values, they’re often used as the body of a method:
315369

370+
{% tabs match-body class=tabs-scala-version %}
371+
{% tab 'Scala 2' for=match-body %}
316372
```scala
317-
def isTruthy(a: Matchable) = a match
373+
def isTruthy(a: Matchable) = a match {
318374
case 0 | "" => false
319375
case _ => true
376+
}
320377
```
378+
{% endtab %}
321379

322-
380+
{% tab 'Scala 3' for=match-body %}
381+
```scala
382+
def isTruthy(a: Matchable) = a match
383+
case 0 | "" => false
384+
case _ => true
385+
```
386+
{% endtab %}
387+
{% endtabs %}
323388

324389
## 9) Ecosystem libraries
325390

@@ -328,8 +393,6 @@ All of the buzzwords like high-performance, type safe, concurrent, asynchronous,
328393

329394
We could list hundreds of libraries here, but fortunately they’re all listed in another location: For those details, see the [“Awesome Scala” list](https://github.com/lauris/awesome-scala).
330395

331-
332-
333396
## 10) Strong type system
334397

335398
Scala has a strong type system, and it’s been improved even more in Scala 3.
@@ -380,7 +443,6 @@ A list of types from the Dotty documentation:
380443
- Bounds
381444
{% endcomment %}
382445

383-
384446
_Safety_ is related to several new and changed features:
385447

386448
- Multiversal equality
@@ -390,6 +452,8 @@ _Safety_ is related to several new and changed features:
390452

391453
Good examples of _ergonomics_ are enumerations and extension methods, which have been added to Scala 3 in a very readable manner:
392454

455+
{% tabs extension %}
456+
{% tab 'Scala 3 Only' for=extension %}
393457
```scala
394458
// enumeration
395459
enum Color:
@@ -401,6 +465,8 @@ extension (c: Circle)
401465
def diameter: Double = c.radius * 2
402466
def area: Double = math.Pi * c.radius * c.radius
403467
```
468+
{% endtab %}
469+
{% endtabs %}
404470

405471
_Performance_ relates to several areas.
406472
One of those is [opaque types][opaque-types].
@@ -416,8 +482,6 @@ Conversely, the goal of opaque types, as described in that SIP, is that “opera
416482

417483
For more type system details, see the [Reference documentation][reference].
418484

419-
420-
421485
## Other great features
422486

423487
Scala has many great features, and choosing a Top 10 list can be subjective.

_zh-cn/overviews/scala3-book/fp-immutable-values.md

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ val b = a.filter(_.startsWith("j"))
3434
同样,在 FP 中,您不会创建具有可变 `var` 构造函数参数的类。
3535
也就是说,你不要这样写:
3636

37-
```scala
3837
```scala
3938
// don’t do this in FP
4039
class Person(var firstName: String, var lastName: String)

0 commit comments

Comments
 (0)