Skip to content

Commit ee9ad6a

Browse files
committed
Update rest of the guide
1 parent 6d8bb4e commit ee9ad6a

8 files changed

+471
-216
lines changed

_style/control-structures.md

Lines changed: 108 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,41 @@ next-page: method-invocation
99
---
1010

1111
All control structures should be written with a space following the
12-
defining keyword:
13-
14-
// right!
15-
if (foo) bar else baz
16-
for (i <- 0 to 10) { ... }
17-
while (true) { println("Hello, World!") }
18-
19-
// wrong!
20-
if(foo) bar else baz
21-
for(i <- 0 to 10) { ... }
22-
while(true) { println("Hello, World!") }
23-
12+
defining keyword. In Scala 3 parentheses around the condition should be omitted:
13+
14+
{% tabs control_structures_1 class=tabs-scala-version%}
15+
{% tab 'Scala 2' for=control_structures_1 %}
16+
```scala
17+
// right!
18+
if (foo) bar else baz
19+
for (i <- 0 to 10) { ... }
20+
while (true) { println("Hello, World!") }
21+
22+
// wrong!
23+
if(foo) bar else baz
24+
for(i <- 0 to 10) { ... }
25+
while(true) { println("Hello, World!") }
26+
```
27+
{% endtab %}
28+
{% tab 'Scala 3' for=control_structures_1 %}
29+
```scala
30+
// right!
31+
if foo then bar else baz
32+
for i <- 0 to 10 do ...
33+
while true do println("Hello, World!")
34+
35+
// wrong!
36+
if(foo) bar else baz
37+
for(i <- 0 to 10) do ...
38+
while(true) do println("Hello, World!")
39+
```
40+
{% endtab %}
41+
{% endtabs %}
2442

2543
## Curly-Braces
2644

27-
Curly-braces should be omitted in cases where the control structure
45+
In Scala 3 using curly-braces is discouraged and the quiet syntax with significant indentation is favoured.
46+
In Scala 2, curly-braces should be omitted in cases where the control structure
2847
represents a pure-functional operation and all branches of the control
2948
structure (relevant to `if`/`else`) are single-line expressions.
3049
Remember the following guidelines:
@@ -41,63 +60,84 @@ Remember the following guidelines:
4160

4261
<!-- necessary to separate the following example from the above bullet list -->
4362

44-
val news = if (foo)
45-
goodNews()
46-
else
47-
badNews()
48-
49-
if (foo) {
50-
println("foo was true")
51-
}
52-
53-
news match {
54-
case "good" => println("Good news!")
55-
case "bad" => println("Bad news!")
56-
}
63+
{% tabs control_structures_2 class=tabs-scala-version%}
64+
{% tab 'Scala 2' for=control_structures_2 %}
65+
```scala
66+
val news = if (foo)
67+
goodNews()
68+
else
69+
badNews()
70+
71+
if (foo) {
72+
println("foo was true")
73+
}
74+
75+
news match {
76+
case "good" => println("Good news!")
77+
case "bad" => println("Bad news!")
78+
}
79+
```
80+
{% endtab %}
81+
{% tab 'Scala 3' for=control_structures_2 %}
82+
```scala
83+
val news = if foo then
84+
goodNews()
85+
else
86+
badNews()
87+
88+
if foo then
89+
println("foo was true")
90+
91+
news match
92+
case "good" => println("Good news!")
93+
case "bad" => println("Bad news!")
94+
```
95+
{% endtab %}
96+
{% endtabs %}
5797

5898
## Comprehensions
5999

60100
Scala has the ability to represent `for`-comprehensions with more than
61101
one generator (usually, more than one `<-` symbol). In such cases, there
62102
are two alternative syntaxes which may be used:
63103

64-
// wrong!
65-
for (x <- board.rows; y <- board.files)
66-
yield (x, y)
67-
68-
// right!
69-
for {
70-
x <- board.rows
71-
y <- board.files
72-
} yield (x, y)
104+
{% tabs control_structures_3 class=tabs-scala-version%}
105+
{% tab 'Scala 2' for=control_structures_3 %}
106+
```scala
107+
// wrong!
108+
for (x <- board.rows; y <- board.files)
109+
yield (x, y)
110+
111+
// right!
112+
for {
113+
x <- board.rows
114+
y <- board.files
115+
} yield (x, y)
116+
```
117+
{% endtab %}
118+
{% tab 'Scala 3' for=control_structures_3 %}
119+
```scala
120+
// wrong!
121+
for x <- board.rows; y <- board.files
122+
yield (x, y)
123+
124+
// right!
125+
for
126+
x <- board.rows
127+
y <- board.files
128+
yield (x, y)
129+
```
130+
{% endtab %}
131+
{% endtabs %}
73132

74133
While the latter style is more verbose, it is generally considered
75134
easier to read and more "scalable" (meaning that it does not become
76135
obfuscated as the complexity of the comprehension increases). You should
77136
prefer this form for all `for`-comprehensions of more than one
78137
generator. Comprehensions with only a single generator (e.g.
79-
`for (i <- 0 to 10) yield i`) should use the first form (parentheses
138+
`for i <- 0 to 10 yield i`) should use the first form (parentheses
80139
rather than curly braces).
81140

82-
The exceptions to this rule are `for`-comprehensions which lack a
83-
`yield` clause. In such cases, the construct is actually a loop rather
84-
than a functional comprehension and it is usually more readable to
85-
string the generators together between parentheses rather than using the
86-
syntactically-confusing `} {` construct:
87-
88-
// wrong!
89-
for {
90-
x <- board.rows
91-
y <- board.files
92-
} {
93-
printf("(%d, %d)", x, y)
94-
}
95-
96-
// right!
97-
for (x <- board.rows; y <- board.files) {
98-
printf("(%d, %d)", x, y)
99-
}
100-
101141
Finally, `for` comprehensions are preferred to chained calls to `map`,
102142
`flatMap`, and `filter`, as this can get difficult to read (this is one
103143
of the purposes of the enhanced `for` comprehension).
@@ -108,11 +148,22 @@ There are certain situations where it is useful to create a short
108148
`if`/`else` expression for nested use within a larger expression. In
109149
Java, this sort of case would traditionally be handled by the ternary
110150
operator (`?`/`:`), a syntactic device which Scala lacks. In these
111-
situations (and really any time you have a extremely brief `if`/`else`
151+
situations (and really any time you have an extremely brief `if`/`else`
112152
expression) it is permissible to place the "then" and "else" branches on
113153
the same line as the `if` and `else` keywords:
114154

115-
val res = if (foo) bar else baz
155+
{% tabs control_structures_4 class=tabs-scala-version%}
156+
{% tab 'Scala 2' for=control_structures_4 %}
157+
```scala
158+
val res = if (foo) bar else baz
159+
```
160+
{% endtab %}
161+
{% tab 'Scala 3' for=control_structures_4 %}
162+
```scala
163+
val res = if foo then bar else baz
164+
```
165+
{% endtab %}
166+
{% endtabs %}
116167

117168
The key here is that readability is not hindered by moving both branches
118169
inline with the `if`/`else`. Note that this style should never be used

_style/declarations.md

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ If a class/object/trait extends anything, the same general rule applies,
5656
put it on one line unless it goes over about 100 characters, and then
5757
put each item on its own line with
5858
[trailing commas](https://docs.scala-lang.org/sips/trailing-commas.html#motivation);
59-
closing parenthesis provides visual separation between constructor arguments and extensions;
59+
closing parenthesis and indentation provide visual separation between constructor arguments and extensions;
6060
empty line should be added to further separate extensions from class implementation:
6161

6262
{% tabs declarations_2 class=tabs-scala-version%}
@@ -70,9 +70,9 @@ class Person(
7070
shoeSize: Int,
7171
favoriteColor: java.awt.Color,
7272
) extends Entity
73-
with Logging
74-
with Identifiable
75-
with Serializable {
73+
with Logging
74+
with Identifiable
75+
with Serializable {
7676

7777
def firstMethod: Foo =
7878
}
@@ -88,9 +88,9 @@ class Person(
8888
shoeSize: Int,
8989
favoriteColor: java.awt.Color,
9090
) extends Entity
91-
with Logging
92-
with Identifiable
93-
with Serializable:
91+
with Logging
92+
with Identifiable
93+
with Serializable:
9494

9595
def firstMethod: Foo =
9696
```
@@ -177,26 +177,6 @@ private def foo(x: Int = 6, y: Int = 7) = x + y
177177
{% endtab %}
178178
{% endtabs %}
179179

180-
#### Procedure Syntax
181-
182-
Avoid the (now deprecated) procedure syntax, as it tends to be confusing for very little gain in brevity.
183-
184-
{% tabs declarations_7 %}
185-
{% tab 'Scala 2 Only' for=declarations_7 %}
186-
```scala
187-
// don't do this
188-
def printBar(bar: Baz) {
189-
println(bar)
190-
}
191-
192-
// write this instead
193-
def printBar(bar: Bar): Unit = {
194-
println(bar)
195-
}
196-
```
197-
{% endtab %}
198-
{% endtabs %}
199-
200180
#### Modifiers
201181

202182
Method modifiers should be given in the following order (when each is
@@ -354,6 +334,7 @@ There are three main reasons you should do this:
354334
def unless(exp: Boolean)(code: => Unit): Unit = {
355335
if (!exp) code
356336
}
337+
357338
unless(x < 5) {
358339
println("x was not less than five")
359340
}
@@ -363,12 +344,14 @@ unless(x < 5) {
363344
```scala
364345
def unless(exp: Boolean)(code: => Unit): Unit =
365346
if (!exp) code
347+
366348
unless(x < 5):
367349
println("x was not less than five")
368350
```
369351
{% endtab %}
370352
{% endtabs %}
371353

354+
{:start="2"}
372355
2. Implicit Parameters
373356

374357
When using implicit parameters, and you use the `implicit` keyword,
@@ -435,7 +418,7 @@ protected def forResource(
435418
{% endtab %}
436419
{% endtabs %}
437420

438-
421+
{:start="2"}
439422
2. Or align the open-paren of the parameter lists, one list per line:
440423

441424
{% tabs declarations_17 class=tabs-scala-version%}

_style/files.md

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,36 @@ previous-page: method-invocation
88
next-page: scaladoc
99
---
1010

11-
As a rule, files should contain a *single* logical compilation unit. By
12-
"logical" I mean a class, trait or object. One exception to this
11+
As a rule, files should contain a *single* class, trait or object. One exception to this
1312
guideline is for classes or traits which have companion objects.
1413
Companion objects should be grouped with their corresponding class or
1514
trait in the same file. These files should be named according to the
1615
class, trait or object they contain:
1716

18-
package com.novell.coolness
17+
{% tabs files_1 class=tabs-scala-version%}
18+
{% tab 'Scala 2' for=files_1 %}
19+
```scala
20+
package com.novell.coolness
1921

20-
class Inbox { ... }
22+
class Inbox { ... }
2123

22-
// companion object
23-
object Inbox { ... }
24+
// companion object
25+
object Inbox { ... }
26+
```
27+
{% endtab %}
28+
{% tab 'Scala 3' for=files_1 %}
29+
```scala
30+
package com.novell.coolness
31+
32+
class Inbox:
33+
...
34+
35+
// companion object
36+
object Inbox:
37+
...
38+
```
39+
{% endtab %}
40+
{% endtabs %}
2441

2542
These compilation units should be placed within a file named
2643
`Inbox.scala` within the `com/novell/coolness` directory. In short, the
@@ -36,11 +53,17 @@ file. One common example is that of a sealed trait and several
3653
sub-classes (often emulating the ADT language feature available in
3754
functional languages):
3855

39-
sealed trait Option[+A]
56+
{% tabs files_2 %}
57+
{% tab 'Scala 2 and 3' for=files_2 %}
58+
```scala
59+
sealed trait Option[+A]
4060

41-
case class Some[A](a: A) extends Option[A]
61+
case class Some[A](a: A) extends Option[A]
4262

43-
case object None extends Option[Nothing]
63+
case object None extends Option[Nothing]
64+
```
65+
{% endtab %}
66+
{% endtabs %}
4467

4568
Because of the nature of sealed superclasses (and traits), all subtypes
4669
*must* be included in the same file. Thus, such a situation definitely

0 commit comments

Comments
 (0)