8000 Some suggestions in the Scala 3 book by julienrf · Pull Request #2062 · scala/docs.scala-lang · GitHub
[go: up one dir, main page]

Skip to content

Some suggestions in the Scala 3 book #2062

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 1 commit into from
Jun 14, 2021
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
4 changes: 2 additions & 2 deletions _overviews/scala3-book/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ The goal of this book is to provide an informal introduction to the Scala langua
It touches on all Scala topics, in a relatively light manner.
If at any time while you’re reading this book and want more information on a specific feature, you’ll find links to our [_Reference_ documentation][reference], which covers many new features of the Scala language in more detail.

Over the course of this book, we hope to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax, and supports functional programming (FP), object-oriented programming (OOP), and a fusion of FP and OOP in a typed setting.
Scala’s syntax, grammar, and features have been re-thought, debated in an open process, and updated in 2020 to be more clear and easier to understand than ever before.
Over the course of this book, we hope to demonstrate that Scala is a beautiful, expressive programming language, with a clean, modern syntax, which supports functional programming (FP) and object-oriented programming (OOP), and that provides a safe static type system.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that “fusion of FP and OOP in a typed setting” was a bit redundant with the previous mentions of FP and OOP, so I’ve changed the last point to highlight only the static type system.

Scala’s syntax, grammar, and features have been re-thought, debated in an open process, and updated in 2020 to be clearer and easier to understand than ever before.

The book begins with a whirlwind tour of many of Scala’s features in the [“A Taste of Scala” section][taste].
After that tour, the sections that follow it provide more details on those language features.
Expand Down
38 changes: 18 additions & 20 deletions _overviews/scala3-book/scala-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ Looking at Scala from the proverbial “30,000 foot view,” you can make the fo
- It has a concise, readable syntax
- It’s statically-typed (but feels dynamic)
- It has an expressive type system
- It’s a pure functional programming (FP) language
- It’s a pure object-oriented programming (OOP) language
- It’s a functional programming (FP) language
- It’s an object-oriented programming (OOP) language
- It supports the fusion of FP and OOP
- Contextual abstractions provide a clear way to implement _term inference_
- It runs on the JVM (and in the browser)
Expand Down Expand Up @@ -63,7 +63,7 @@ val newNumbers = double(oldNumbers)
```

That code instructs the compiler what to do on a step-by-step basis.
Instead, we write high-level, functional code using higher-order functions and lambdas like this to achieve the same effect:
Instead, we write high-level, functional code using higher-order functions and lambdas like this to compute the same result:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer “computing a result” over “achieving an effect”, which sounded more imperative to me.


```scala
val newNumbers = oldNumbers.map(_ * 2)
Expand Down Expand Up @@ -92,7 +92,7 @@ nums.filter(i => i > 1)
nums.filter(_ > 1)
```

And traits, classes, and methods are defined with a clean, light syntax:
Traits, classes, and methods are defined with a clean, light syntax:

```scala
trait Animal:
Expand Down Expand Up @@ -128,15 +128,13 @@ As Heather Miller states, Scala is considered to be a [strong, statically-typed

- Correctness: you catch most errors at compile-time
- Great IDE support
- Code completion
- Reliable code completion
- Catching errors at compile-time means catching mistakes as you type
- Easy and reliable refactoring
- Reliable code completion
- You can refactor your code with confidence
- Method type declarations tell readers what the method does, and help serve as documentation
- Types make your code easier to maintain
- Scalability: types help ensure correctness across arbitrarily large applications and development teams
- Strong typing in combination with excellent inference enables mechanisms like [contextual abstraction]({{ site.scala3ref }}/contextual/motivation.html) that allows you to omit boilerplate code. Often, this boilerplate code can be inferred by the compiler, based on type definitions and a given context (e.g. method arguments for implicit parameters).
- Scalability and maintainability: types help ensure correctness across arbitrarily large applications and development teams
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have merged “types make your code easier to maintain” and “Scalability” into just “Scalability and maintainability”.

- Strong typing in combination with excellent inference enables mechanisms like [contextual abstraction]({{ site.scala3ref }}/contextual/motivation.html) that allows you to omit boilerplate code. Often, this boilerplate code can be inferred by the compiler, based on type definitions and a given context.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed “method arguments for implicit parameters”, I think it’s too early to introduce this jargon.


{% comment %}
In that list:
Expand All @@ -156,11 +154,11 @@ In that list:

- i removed these items until we can replace them:
* [Compound types](/tour/compound-types.html)
* [Implicit parameters](/tour/implicit-parameters.html) and [conversions](/tour/implicit-conversions.html)
* [ 8000 conversions](/tour/implicit-conversions.html)
* [Explicitly typed self references](/tour/self-types.html)
{% endcomment %}

Scala’s expressive type system enforces, at compile-time, that abstractions are used in a safe and coherent manner.
Scala’s type system enforces, at compile-time, that abstractions are used in a safe and coherent manner.
In particular, the type system supports:

- [Type inference](/tour/type-inference.html)
Expand All @@ -187,11 +185,11 @@ In particular, the type system supports:
In combination, these features provide a powerful basis for the safe reuse of programming abstractions and for the type-safe extension of software.


### A pure FP language
### A functional programming language

Scala is a functional programming (FP) language, meaning:

- Functions are variables, and can be passed around like any other variable
- Functions are values, and can be passed around like any other value
- Higher-order functions are directly supported
- Lambdas are built in
- Everything in Scala is an expression that returns a value
Expand All @@ -200,10 +198,10 @@ Scala is a functional programming (FP) language, meaning:
- Those collection classes come with dozens of functional methods: they don’t mutate the collection, but instead return an updated copy of the data


### A pure OOP language
### An object-oriented language

Scala is a _pure_ object-oriented programming (OOP) language.
Every variable is an object and every “operator” is a method.
Scala is an object-oriented programming (OOP) language.
Every value is an instance of a class and every “operator” is a method.

In Scala, all types inherit from a top-level class `Any`, whose immediate children are `AnyVal` (_value types_, such as `Int` and `Boolean`) and `AnyRef` (_reference types_, as in Java).
This means that the Java distinction between primitive types and boxed types (e.g. `int` vs. `Integer`) isn’t present in Scala.
Expand Down Expand Up @@ -236,9 +234,9 @@ Following Haskell, Scala was the second popular language to have some form of _i
In Scala 3 these concepts have been completely re-thought and more clearly implemented.

The core idea is _term inference_: Given a type, the compiler synthesizes a “canonical” term that has that type.
In Scala, an implicit parameter directly leads to an inferred argument term that could also be written down explicitly.
In Scala, a context parameter directly leads to an inferred argument term that could also be written down explicitly.

Use cases for this concept include implementing type classes, establishing context, dependency injection, expressing capabilities, computing new types, and proving relationships between them.
Use cases for this concept include implementing [type classes]({% link _overviews/scala3-book/ca-type-classes.md %}), establishing context, dependency injection, expressing capabilities, computing new types, and proving relationships between them.

Scala 3 makes this process more clear than ever before.
Read about contextual abstractions in the [Reference documentation]({{ site.scala3ref }}/contextual/motivation.html).
Expand Down Expand Up @@ -442,7 +440,7 @@ Serialization:

- [ScalaPB](https://github.com/scalapb/ScalaPB)

Science and data analysis:
### Science and data analysis:

- [Algebird](https://github.com/twitter/algebird)
- [Spire](https://github.com/typelevel/spire)
Expand All @@ -461,7 +459,7 @@ Science and data analysis:
- [TensorFlow Scala](https://github.com/eaplatanios/tensorflow_scala)


### FP & FRP
### Functional Programming & Functional Reactive Programming

FP:

Expand Down
12 changes: 5 additions & 7 deletions _overviews/scala3-book/taste-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,13 @@ nums.map(_.toUpperCase) // List("ONE", "TWO")
nums.flatMap(_.toUpperCase) // List('O', 'N', 'E', 'T', 'W', 'O')
```

These examples show how the “fold” and “reduce” methods are used to sum the values in a sequence of integers:
These examples show how the “foldLeft” and “reduceLeft” methods are used to sum the values in a sequence of integers:

```scala
val firstTen = (1 to 10).toList // List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

firstTen.reduce(_ + _) // 55
firstTen.reduceLeft(_ + _) // 55
firstTen.fold(100)(_ + _) // 155 (100 is a “seed” value)
firstTen.foldLeft(100)(_ + _) // 155
firstTen.foldLeft(100)(_ + _) // 155 (100 is a “seed” value)
```

There are many more methods available to Scala collections classes, and they’re demonstrated in the [Collections chapter][collections], and in the [API Documentation][api].
Expand All @@ -93,9 +91,9 @@ val t = (11, "eleven", Person("Eleven"))
Once you have a tuple, you can access its values by binding them to variables, or access them by number:

```scala
t._1 // 11
t._2 // "eleven"
t._3 // Person("Eleven")
t(0) // 11
t(1) // "eleven"
t(2) // Person("Eleven")
```

You can also use this _extractor_ approach to assign the tuple fields to variable names:
Expand Down
17 changes: 9 additions & 8 deletions _overviews/scala3-book/taste-control-structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ This example shows (a) how to use a `match` expression as the body of a method,

```scala
// getClassAsString is a method that takes a single argument of any type.
def getClassAsString(x: Any): String = x match
def getClassAsString(x: Matchable): String = x match
case s: String => s"'$s' is a String"
case i: Int => "Int"
case d: Double => "Double"
Expand All @@ -199,6 +199,10 @@ getClassAsString("hello") // 'hello' is a String
getClassAsString(List(1, 2, 3)) // List
```

The method `getClassAsString` takes as a parameter a value of type [Matchable]({{ site.scala3ref }}/other-new-features/matchable.html), which can be
any type supporting pattern matching (some types don’t support pattern matching because this could
break encapsulation).

There’s _much_ more to pattern matching in Scala.
Patterns can be nested, results of patterns can be bound, and pattern matching can even be user-defined.
See the pattern matching examples in the [Control Structures chapter][control] for more details.
Expand Down Expand Up @@ -231,29 +235,26 @@ It’s one-line syntax looks like this:
while x >= 0 do x = f(x)
```

Again, Scala’s control structure syntax is flexible, and you can write this code in different ways depending on your preferences:
In Scala 2, the syntax was a bit different. The condition was surrounded by parentheses, and
there was no `do` keyword:
Comment on lines -234 to +239
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it’s preferable to mention one reference syntax and to say that the alternative syntax is supported for compatibility reasons, primarily, otherwise I’m afraid readers will feel lost if we show them several ways of doing one thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. If we ever create the ability to show notes/tips/asides, I would put the Scala 2 text in one of those. (I’ve attached two images from the Cookbook to show what I mean by notes, tips, and asides.)

tip
note


```scala
while (x >= 0) do x = f(x)
while (x >= 0) { x = f(x) }
```

Scala 3 still supports the Scala 2 syntax for the sake of compatibility.

The `while` loop multiline syntax looks like this:

```scala
var x = 1

// without parentheses
while
x < 3
do
println(x)
x += 1

// with parentheses
while (x < 3)
println(x)
x += 1
```


Expand Down
4 changes: 2 additions & 2 deletions _overviews/scala3-book/taste-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ next-page: taste-objects

Scala has most features you’d expect in a functional programming language, including:

- Lambdas
- Lambdas (anonymous functions)
- Higher-order functions (HOFs)
- Immutable collections in the standard library

Lambdas, also known as _anonymous functions_, are a big part of keeping your code concise but readable.

The `map` method of the `List` class is a typical example of a higher-order function---a function that takes a lambda as parameter.
The `map` method of the `List` class is a typical example of a higher-order function---a function that takes a function as parameter.

These two examples are equivalent, and show how to multiply each number in a list by `2` by passing a lambda into the `map` method:

Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-book/taste-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ extension (s: String)
## See also

Scala Methods can be much more powerful: they can take type parameters and context parameters.
They are covered in detail in the [Data Modeling][data-1] section.
They are covered in detail in the [Domain Modeling][data-1] section.



Expand Down
14 changes: 7 additions & 7 deletions _overviews/scala3-book/taste-modeling.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ c.stopRunning() // "No need to stop"
```

If that code makes sense---great, you’re comfortable with traits as interfaces.
If not, don’t worry, they’re explained in more detail in the [Data Modeling][data-1] chapter.
If not, don’t worry, they’re explained in more detail in the [Domain Modeling][data-1] chapter.


### Classes
Expand All @@ -106,7 +106,7 @@ Notice that the class declaration creates a constructor:
val p = Person("John", "Stephens")
```

Constructors and other class-related topics are covered in the [Data Modeling][data-1] chapter.
Constructors and other class-related topics are covered in the [Domain Modeling][data-1] chapter.


## FP Domain Modeling
Expand Down Expand Up @@ -170,7 +170,7 @@ enum Nat:
case Succ(pred: Nat)
```

Enums are covered in detail in the [Data Modeling][data-1] section of this book, and in the [Reference documentation]({{ site.scala3ref }}/enums/enums.html).
Enums are covered in detail in the [Domain Modeling][data-1] section of this book, and in the [Reference documentation]({{ site.scala3ref }}/enums/enums.html).


### Case classes
Expand All @@ -183,7 +183,7 @@ When the compiler sees the `case` keyword in front of a `class` it has these eff
- An `unapply` method is generated, which lets you use case classes in more ways in `match` expressions.
- A `copy` method is generated in the class.
This provides a way to create updated copies of the object without changing the original object.
- `equals` and `hashCode` methods are generated.
- `equals` and `hashCode` methods are generated to implement structural equality.
- A default `toString` method is generated, which is helpful for debugging.


Expand All @@ -206,7 +206,7 @@ case class Person(
val p = Person("Reginald Kenneth Dwight", "Singer")

// a good default toString method
p // Person = Person(Reginald Kenneth Dwight,Singer)
p 179B // : Person = Person(Reginald Kenneth Dwight,Singer)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not entirely sure what was the intent by writing “Person = Person(...)”. If the goal is to look like the output of a worksheet in Metals, then we should add the colons just before the inferred type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you can just show the Person(Reginald Kenneth Dwight,Singer) part there.

I’m not sure why I included the Person = Person... part, that’s not something I normally do.


// can access its fields, which are immutable
p.name // "Reginald Kenneth Dwight"
Expand All @@ -215,10 +215,10 @@ p.name = "Joe" // error: can’t reassign a val field
// when you need to make a change, use the `copy` method
// to “update as you copy”
val p2 = p.copy(name = "Elton John")
p2 // Person = Person(Elton John,Singer)
p2 // : Person = Person(Elton John,Singer)
```

See the [Data Modeling][data-1] sections for many more details on `case` classes.
See the [Domain Modeling][data-1] sections for many more details on `case` classes.



Expand Down
4 changes: 2 additions & 2 deletions _overviews/scala3-book/taste-objects.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Objects
title: Singleton Objects
type: section
description: This section provides an introduction to the use of objects in Scala 3.
description: This section provides an introduction to the use of singleton objects in Scala 3.
num: 12
previous-page: taste-functions
next-page: taste-collections
Expand Down
Loading
0