Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit af62827

Browse files
committedJun 30, 2021
Rework syntax rewriting doc
Give a bit more details about the new syntax. Make it clear that one must rewrite to the new control structure before rewriting to the indentation based syntax. Show the example in that order. Simplify the example (it is not a reference).
1 parent 99a53de commit af62827

File tree

1 file changed

+50
-88
lines changed

1 file changed

+50
-88
lines changed
 

‎_overviews/scala3-migration/tooling-syntax-rewriting.md

Lines changed: 50 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ previous-page: tutorial-macro-mixing
77
next-page: incompatibility-table
88
---
99

10-
Scala 3 gives Scala developers the option to adopt the new and optional significant indentation syntax.
11-
The Scala 2 syntax which uses curly braces to group expressions remains fully supported, and we will refer to it as the classical braces syntax.
10+
Scala 3 extends the syntax of the Scala language with the new control syntax and the significant indentation syntax.
11+
Both are optional so that the Scala 2 code style is still perfectly valid in Scala 3.
1212

13-
Scala 3 also introduces a new syntax for control structures, which applies to `if`-expressions, `while`-loops, and `for`-expressions.
13+
The new syntax for control structure makes it possible to write the condition of an `if`-expression, the condition of a `while`-loop or the enumerators of a `for`-expression without enclosing parentheses.
1414

15-
Converting existing code to use the new syntax by hand would be tedious and error-prone.
16-
The good news is the Scala 3 compiler can do the hard work for us!
15+
The significant indentation syntax makes braces `{...}` not needed in many occurences: class and method bodies, `if`-expressions, `match`-expressions and more.
16+
You can find a complete description in the [Optional Braces](http://dotty.epfl.ch/docs/reference/other-new-features/indentation.html) page of the Scala 3 reference website.
17+
18+
Converting existing Scala code to the new syntax by hand is tedious and error-prone.
19+
In this chapter we show how you can use the compiler to rewrite your code automatically from the classic Scala 2 style to the new style or backward.
1720

1821
## Syntax Rewriting Options
1922

@@ -41,43 +44,33 @@ where possible standard options include:
4144

4245
Each of the first four options corresponds to a specific syntax:
4346

47+
| Syntax | Option |
48+
| - | - |
49+
| New Control Structure | `-new-syntax` |
50+
| Old Control Structure | `-old-syntax` |
51+
4452
| Syntax | Compiler Option |
4553
|-|-|
4654
| Significant Indentation | `-indent` |
4755
| Classical Braces | `-noindent` |
4856

49-
| Syntax | Option |
50-
| - | - |
51-
| New Control Structure | `-new-syntax` |
52-
| Old Control Structure | `-old-syntax` |
5357

5458
As we will see in further detail these options can be used in combination with the `-rewrite` option to automate the conversion to a particular syntax.
5559
Let's have a look at how this works in a small example.
5660

57-
## Significant Indentation Syntax
61+
## The New Syntax Rewrites
5862

59-
Given the following source code written in the Scala 2 style:
63+
Given the following source code written in a Scala 2 style.
6064

6165
```scala
62-
object Counter {
63-
enum Protocol {
64-
case Reset
65-
case MoveBy(step: Int)
66-
}
67-
}
68-
69-
case class Animal(name: String)
70-
71-
trait Incrementer {
72-
def increment(n: Int): Int
73-
}
74-
7566
case class State(n: Int, minValue: Int, maxValue: Int) {
67+
7668
def inc: State =
7769
if (n == maxValue)
7870
this
7971
else
8072
this.copy(n = n + 1)
73+
8174
def printAll: Unit = {
8275
println("Printing all")
8376
for {
@@ -88,67 +81,60 @@ case class State(n: Int, minValue: Int, maxValue: Int) {
8881
}
8982
```
9083

91-
Assume that we want to convert this piece of code to the significant indentation syntax.
92-
We can use the `-indent -rewrite` options by adding them to the `scalacOptions` setting in our sbt build:
84+
We will be able to move it to new syntax automatically in two steps: first by using the new control structure rewrite (`-new-syntax -rewrite`) and then the significant indentation rewrite (`-indent -rewrite`).
85+
86+
> The `-indent` option does not work on the classic control structures.
87+
> So make sure to run the two steps in the correct order.
88+
89+
> Unfortunately, the compiler is not able to apply both steps at the same time: <del>`-indent -new-syntax -rewrite`</del>.
90+
91+
### New Control Structure
92+
93+
We can use the `-new-syntax -rewrite` options by adding them to the list of scalac options in our build tool.
9394

9495
```scala
9596
// build.sbt
96-
scalacOptions ++= Seq("-indent", "-rewrite")
97+
scalacOptions ++= Seq("-new-syntax", "-rewrite")
9798
```
9899

99100
After compiling the code, the result looks as follows:
100101

101102
```scala
102-
object Counter:
103-
enum Protocol:
104-
case Reset
105-
case MoveBy(step: Int)
106-
107-
case class Animal(name: String)
108-
109-
trait Incrementer:
110-
def increment(n: Int): Int
111-
112-
case class State(n: Int, minValue: Int, maxValue: Int):
103+
case class State(n: Int, minValue: Int, maxValue: Int) {
104+
113105
def inc: State =
114-
if (n == maxValue)
106+
if n == maxValue then
115107
this
116108
else
117109
this.copy(n = n + 1)
118-
def printAll: Unit =
110+
111+
def printAll: Unit = {
119112
println("Printing all")
120-
for {
113+
for
121114
i <- minValue to maxValue
122115
j <- 0 to n
123-
} println(i + j)
116+
do println(i + j)
117+
}
118+
}
124119
```
125120

126-
A few things to observe after the switch to the significant indentation syntax:
127-
- The number of lines was reduced by 4 because of the elimination of a series of closing curly braces
128-
- The control structures are unchanged
121+
Notice that the parentheses around the `n == maxValue` disappeared, as well as the braces around the `i <- minValue to maxValue` and `j <- 0 to n` enumerators.
129122

130-
## New Control Structure
123+
### Significant Indentation Syntax
131124

132-
After this first rewrite, we can jump to the new control structure syntax by using `-new-syntax -rewrite`.
125+
After this first rewrite, we can use the significant indentation syntax to remove the remaining braces.
126+
To do that we use the `-indent` option in combination with the `-rewrite` option.
133127
It leads us to the following version:
134128

135129
```scala
136-
object Counter:
137-
enum Protocol:
138-
case Reset
139-
case MoveBy(step: Int)
140-
141-
case class Animal(name: String)
142-
143-
trait Incrementer:
144-
def increment(n: Int): Int
145-
146130
case class State(n: Int, minValue: Int, maxValue: Int):
131+
147132
def inc: State =
148133
if n == maxValue then
149134
this
150135
else
151136
this.copy(n = n + 1)
137+
152138
def printAll: Unit =
153139
println("Printing all")
154140
for
@@ -157,37 +143,24 @@ case class State(n: Int, minValue: Int, maxValue: Int):
157143
do println(i + j)
158144
```
159145

160-
We moved to the new syntaxes of Scala 3 in two steps: first we used `-indent -rewrite` then `-new-syntax -rewrite`.
161-
We could also apply the new control structure syntax before the significant indentation syntax.
162-
But the compiler is not able to apply both at the same time: <del>`-indent -new-syntax -rewrite`</del>.
146+
We can observe that the number of lines was reduced by 2 thanks to the elimination of the closing curly braces.
163147

164-
## Moving back to Classic syntax
148+
## Moving back to the Classic syntax
165149

166150
Starting from the latest state of our code sample, we can move backwards to its initial state.
167151

168-
Let's rewrite to the braces syntax and retain the new control structures syntax.
152+
Let's rewrite the code using braces while retaining the new control structures syntax.
169153
After compiling with the `-no-indent -rewrite` options, we obtain the following result:
170154

171155
```scala
172-
object Counter {
173-
enum Protocol {
174-
case Reset
175-
case MoveBy(step: Int)
176-
}
177-
}
178-
179-
case class Animal(name: String)
180-
181-
trait Incrementer {
182-
def increment(n: Int): Int
183-
}
184-
185156
case class State(n: Int, minValue: Int, maxValue: Int) {
157+
186158
def inc: State =
187159
if n == maxValue then
188160
this
189161
else
190162
this.copy(n = n + 1)
163+
191164
def printAll: Unit = {
192165
println("Printing all")
193166
for {
@@ -202,25 +175,14 @@ case class State(n: Int, minValue: Int, maxValue: Int) {
202175
Applying one more rewrite, with `-old-syntax -rewrite`, takes us back to the original Scala 2-style code.
203176

204177
```scala
205-
object Counter {
206-
enum Protocol {
207-
case Reset
208-
case MoveBy(step: Int)
209-
}
210-
}
211-
212-
case class Animal(name: String)
213-
214-
trait Incrementer {
215-
def increment(n: Int): Int
216-
}
217-
218178
case class State(n: Int, minValue: Int, maxValue: Int) {
179+
219180
def inc: State =
220181
if (n == maxValue)
221182
this
222183
else
223184
this.copy(n = n + 1)
185+
224186
def printAll: Unit = {
225187
println("Printing all")
226188
for {

0 commit comments

Comments
 (0)
Please sign in to comment.