Skip to content

Why scala 3 tabs code #2510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 88 additions & 24 deletions _overviews/scala3-book/why-scala-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ TODO: Is “Scala 3 Benefits” a better title?
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
{% endcomment %}


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

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



## 1) FP/OOP fusion

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

{% tabs list %}
{% tab 'Scala 2 and 3' for=list %}
```scala
val x = List(1, 2, 3)
```
{% endtab %}
{% endtabs %}

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`.
Those types are similarly composed of other small, modular units of code.

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:

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

Expand All @@ -57,41 +60,55 @@ xs.filter(_ < 3) // List(1, 2)
xs.find(_ > 3) // Some(4)
xs.takeWhile(_ < 3) // List(1, 2)
```
{% endtab %}
{% endtabs %}

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



## 2) A dynamic feel

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

{% tabs dynamic %}
{% tab 'Scala 2 and 3' for=dynamic %}
```scala
val a = 1
val b = "Hello, world"
val c = List(1,2,3,4,5)
val stuff = ("fish", 42, 1_234.5)
```
{% endtab %}
{% endtabs %}

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

{% tabs dynamic-hof %}
{% tab 'Scala 2 and 3' for=dynamic-hof %}
```scala
list.filter(_ < 4)
list.map(_ * 2)
list.filter(_ < 4)
.map(_ * 2)
```
{% endtab %}
{% endtabs %}

and when defining methods:

{% tabs dynamic-method %}
{% tab 'Scala 2 and 3' for=dynamic-method %}
```scala
def add(a: Int, b: Int) = a + b
```
{% endtab %}
{% endtabs %}

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

{% tabs union %}
{% tab 'Scala 3 Only' for=union %}
```scala
// union type parameter
def help(id: Username | Password) =
Expand All @@ -103,21 +120,27 @@ def help(id: Username | Password) =
// union type value
val b: Password | Username = if (true) name else password
```


{% endtab %}
{% endtabs %}

## 3) Concise syntax

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

{% tabs concise %}
{% tab 'Scala 2 and 3' for=concise %}
```scala
val a = 1
val b = "Hello, world"
val c = List(1,2,3)
```
{% endtab %}
{% endtabs %}

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

{% tabs enum %}
{% tab 'Scala 3 Only' for=enum %}
```scala
trait Tail:
def wagTail(): Unit
Expand All @@ -134,18 +157,23 @@ case class Person(
age: Int
)
```
{% endtab %}
{% endtabs %}

Higher-order functions are concise:

{% tabs list-hof %}
{% tab 'Scala 2 and 3' for=list-hof %}

```scala
list.filter(_ < 4)
list.map(_ * 2)
```
{% endtab %}
{% endtabs %}

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



## 4) Implicits, simplified

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

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.



## 5) Seamless Java integration

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

See that chapter for more details on these features.



## 6) Client &amp; server

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

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.



## 7) Standard library methods

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.
Expand All @@ -225,6 +247,8 @@ While these all use the `List` class, the same methods work with other collectio

Here are some examples:

{% tabs list-more %}
{% tab 'Scala 2 and 3' for=list-more %}
```scala
List.range(1, 3) // List(1, 2)
List.range(start = 1, end = 6, step = 2) // List(1, 3, 5)
Expand Down Expand Up @@ -263,36 +287,50 @@ nums.sorted // List(1, 5, 7, 8, 10)
nums.sortWith(_ < _) // List(1, 5, 7, 8, 10)
nums.sortWith(_ > _) // List(10, 8, 7, 5, 1)
```


{% endtab %}
{% endtabs %}

## 8) Built-in best practices

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

{% tabs val %}
{% tab 'Scala 2 and 3' for=val %}
```scala
val a = 1 // immutable variable
```
{% endtab %}
{% endtabs %}

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

{% tabs list-map %}
{% tab 'Scala 2 and 3' for=list-map %}
```scala
val b = List(1,2,3) // List is immutable
val c = Map(1 -> "one") // Map is immutable
```
{% endtab %}
{% endtabs %}

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

{% tabs case-class %}
{% tab 'Scala 2 and 3' for=case-class %}
```scala
case class Person(name: String)
val p = Person("Michael Scott")
p.name // Michael Scott
p.name = "Joe" // compiler error (reassignment to val name)
```
{% endtab %}
{% endtabs %}

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:

{% tabs higher-order %}
{% tab 'Scala 2 and 3' for=higher-order %}
```scala
a.dropWhile(_ < 25)
a.filter(_ < 25)
Expand All @@ -301,25 +339,52 @@ a.filter(_ < 30).map(_ * 10)
nums.sortWith(_ < _)
nums.sortWith(_ > _)
```
{% endtab %}
{% endtabs %}

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

{% tabs match class=tabs-scala-version %}
{% tab 'Scala 2' for=match %}
```scala
val numAsString = i match {
case 1 | 3 | 5 | 7 | 9 => "odd"
case 2 | 4 | 6 | 8 | 10 => "even"
case _ => "too big"
}
```
{% endtab %}

{% tab 'Scala 3' for=match %}
```scala
val numAsString = i match
case 1 | 3 | 5 | 7 | 9 => "odd"
case 2 | 4 | 6 | 8 | 10 => "even"
case _ => "too big"
```
{% endtab %}
{% endtabs %}

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

{% tabs match-body class=tabs-scala-version %}
{% tab 'Scala 2' for=match-body %}
```scala
def isTruthy(a: Matchable) = a match
def isTruthy(a: Matchable) = a match {
case 0 | "" => false
case _ => true
}
```
{% endtab %}


{% tab 'Scala 3' for=match-body %}
```scala
def isTruthy(a: Matchable) = a match
case 0 | "" => false
case _ => true
```
{% endtab %}
{% endtabs %}

## 9) Ecosystem libraries

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

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).



## 10) Strong type system

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


_Safety_ is related to several new and changed features:

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

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

{% tabs extension %}
{% tab 'Scala 3 Only' for=extension %}
```scala
// enumeration
enum Color:
Expand All @@ -401,6 +465,8 @@ extension (c: Circle)
def diameter: Double = c.radius * 2
def area: Double = math.Pi * c.radius * c.radius
```
{% endtab %}
{% endtabs %}

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

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



## Other great features

Scala has many great features, and choosing a Top 10 list can be subjective.
Expand Down
1 change: 0 additions & 1 deletion _zh-cn/overviews/scala3-book/fp-immutable-values.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ val b = a.filter(_.startsWith("j"))
同样,在 FP 中,您不会创建具有可变 `var` 构造函数参数的类。
也就是说,你不要这样写:

```scala
```scala
// don’t do this in FP
class Person(var firstName: String, var lastName: String)
Expand Down