Skip to content

Commit b1a6867

Browse files
committed
Updates to documentation
Drop fewerbraces.md, it's now fully part of indentation.md.
1 parent 32079ff commit b1a6867

File tree

4 files changed

+66
-114
lines changed

4 files changed

+66
-114
lines changed

docs/_docs/internals/syntax.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,17 @@ The lexical analyzer also inserts `indent` and `outdent` tokens that represent r
9696
In the context-free productions below we use the notation `<<< ts >>>`
9797
to indicate a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent`. Analogously, the
9898
notation `:<<< ts >>>` indicates a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent` that follows
99-
a `:` at the end of a line.
99+
a `colon` token.
100100

101+
A `colon` token reads as the standard colon "`:`" but is generated instead of it where `colon` is legal according to the context free syntax, but only if the previous token
102+
is an alphanumeric identifier, a backticked identifier, or one of the tokens `this`, `super`, "`)`", and "`]`".
101103

102104
```
105+
colon ::= ':' -- with side conditions explained above
103106
<<< ts >>> ::= ‘{’ ts ‘}’
104107
| indent ts outdent
105108
:<<< ts >>> ::= [nl] ‘{’ ts ‘}’
106-
| `:` indent ts outdent
109+
| colon indent ts outdent
107110
```
108111

109112
## Keywords
@@ -197,7 +200,7 @@ FunArgTypes ::= FunArgType { ‘,’ FunArgType }
197200
ParamType ::= [‘=>’] ParamValueType
198201
ParamValueType ::= Type [‘*’] PostfixOp(t, "*")
199202
TypeArgs ::= ‘[’ Types ‘]’ ts
200-
Refinement ::= ‘{’ [RefineDcl] {semi [RefineDcl]} ‘}’ ds
203+
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>> ds
201204
TypeBounds ::= [‘>:’ Type] [‘<:’ Type] TypeBoundsTree(lo, hi)
202205
TypeParamBounds ::= TypeBounds {‘:’ Type} ContextBounds(typeBounds, tps)
203206
Types ::= Type {‘,’ Type}
@@ -234,7 +237,7 @@ Catches ::= ‘catch’ (Expr | ExprCaseClause)
234237
PostfixExpr ::= InfixExpr [id] PostfixOp(expr, op)
235238
InfixExpr ::= PrefixExpr
236239
| InfixExpr id [nl] InfixExpr InfixOp(expr, op, expr)
237-
| InfixExpr id ‘:’ IndentedExpr
240+
| InfixExpr id ColonArgument
238241
| InfixExpr MatchClause
239242
MatchClause ::= ‘match’ <<< CaseClauses >>> Match(expr, cases)
240243
PrefixExpr ::= [PrefixOperator] SimpleExpr PrefixOp(expr, op)
@@ -253,13 +256,13 @@ SimpleExpr ::= SimpleRef
253256
| SimpleExpr ‘.’ MatchClause
254257
| SimpleExpr TypeArgs TypeApply(expr, args)
255258
| SimpleExpr ArgumentExprs Apply(expr, args)
256-
| SimpleExpr ‘:’ ColonArgument -- under language.experimental.fewerBraces
259+
| SimpleExpr ColonArgument -- under language.experimental.fewerBraces
257260
| SimpleExpr ‘_’ PostfixOp(expr, _) (to be dropped)
258261
| XmlExpr -- to be dropped
259-
ColonArgument ::= indent CaseClauses | Block outdent
260-
| FunParams (‘=>’ | ‘?=>’) ColonArgBody
261-
| HkTypeParamClause ‘=>’ ColonArgBody
262-
ColonArgBody ::= indent (CaseClauses | Block) outdent
262+
ColonArgument ::= colon [LambdaStart]
263+
indent (CaseClauses | Block) outdent
264+
LambdaStart ::= FunParams (‘=>’ | ‘?=>’)
265+
| HkTypeParamClause ‘=>’
263266
ExprSplice ::= spliceId -- if inside quoted block
264267
| ‘$’ ‘{’ Block ‘}’ -- unless inside quoted pattern
265268
| ‘$’ ‘{’ Pattern ‘}’ -- when inside quoted pattern

docs/_docs/reference/experimental/fewer-braces.md

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,78 +4,4 @@ title: "Fewer Braces"
44
nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/fewer-braces.html
55
---
66

7-
By and large, the possible indentation regions coincide with those regions where braces `{...}` are also legal, no matter whether the braces enclose an expression or a set of definitions. There is one exception, though: Arguments to function can be enclosed in braces but they cannot be simply indented instead. Making indentation always significant for function arguments would be too restrictive and fragile.
8-
9-
To allow such arguments to be written without braces, a variant of the indentation scheme is implemented under language import
10-
```scala
11-
import language.experimental.fewerBraces
12-
```
13-
Alternatively, it can be enabled with command line option `-language:experimental.fewerBraces`.
14-
15-
This variant is more contentious and less stable than the rest of the significant indentation scheme. It allows to replace a function argument in braces by a `:` at the end of a line and indented code, similar to the convention for class bodies. The `:` can
16-
optionally be followed by the parameter part of a function literal.
17-
18-
## Using `:` At End Of Line
19-
20-
21-
Similar to what is done for classes and objects, a `:` that follows a function reference at the end of a line means braces can be omitted for function arguments. Example:
22-
```scala
23-
times(10):
24-
println("ah")
25-
println("ha")
26-
```
27-
28-
The colon can also follow an infix operator:
29-
30-
```scala
31-
credentials ++ :
32-
val file = Path.userHome / ".credentials"
33-
if file.exists
34-
then Seq(Credentials(file))
35-
else Seq()
36-
```
37-
38-
Function calls that take multiple argument lists can also be handled this way:
39-
40-
```scala
41-
val firstLine = files.get(fileName).fold:
42-
val fileNames = files.values
43-
s"""no file named $fileName found among
44-
|${values.mkString(\n)}""".stripMargin
45-
:
46-
f =>
47-
val lines = f.iterator.map(_.readLine)
48-
lines.mkString("\n)
49-
```
50-
51-
52-
## Lambda Arguments Without Braces
53-
54-
The `:` can optionally be followed by the parameter part of a function literal:
55-
```scala
56-
val xs = elems.map: x =>
57-
val y = x - 1
58-
y * y
59-
xs.foldLeft(0): (x, y) =>
60-
x + y
61-
```
62-
Braces can be omitted if the lambda starts with a parameter list and an arrow symbol `=>` or `?=>`.
63-
The arrow is followed on the next line(s) by the body of the functional literal which must be indented
64-
relative to the previous line.
65-
66-
## Syntax Changes
67-
68-
As a lexical change, a `:` at the end of a line is now always treated as a
69-
"colon at end of line" token.
70-
71-
The context free grammar changes as follows:
72-
```
73-
SimpleExpr ::= ...
74-
| SimpleExpr ‘:’ ColonArgument
75-
76-
| SimpleExpr FunParams (‘=>’ | ‘?=>’) IndentedArgument
77-
ColonArgument ::= indent CaseClauses | Block outdent
78-
| FunParams (‘=>’ | ‘?=>’) ColonArgBody
79-
| HkTypeParamClause ‘=>’ ColonArgBody
80-
ColonArgBody ::= indent (CaseClauses | Block) outdent
81-
```
7+
The documentation contained in this file is now part of [./indentation.html].

docs/_docs/reference/other-new-features/indentation.md

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ There are two rules:
6161

6262
- after the leading parameters of an `extension`, or
6363
- after a `with` in a given instance, or
64-
- after a ": at end of line" token (see below)
64+
- after a `:` at the start of a template body (see discussion of `<colon>` below), or
6565
- after one of the following tokens:
6666

6767
```
@@ -134,12 +134,14 @@ is parsed as `if x then a + b + c else d`.
134134

135135
The Scala grammar uses the term _template body_ for the definitions of a class, trait, or object that are normally enclosed in braces. The braces around a template body can also be omitted by means of the following rule.
136136

137-
If at the point where a template body can start there is a `:` that occurs at the end
138-
of a line, and that is followed by at least one indented statement, the recognized
139-
token is changed from ":" to ": at end of line". The latter token is one of the tokens
140-
that can start an indentation region. The Scala grammar is changed so an optional ": at end of line" is allowed in front of a template body.
137+
A template body can alternatively consist of a colon followed by one or more indented statements. To this purpose we introduce a new `<colon>` token that reads as
138+
the standard colon "`:`" but is generated instead of it where `<colon>`
139+
is legal according to the context free syntax, but only if the previous token
140+
is an alphanumeric identifier, a backticked identifier, or one of the tokens `this`, `super`, "`)`", and "`]`".
141141

142-
Analogous rules apply for enum bodies and local packages containing nested definitions.
142+
An indentation region can start after a `<colon>`. A template body may be either enclosed in braces, or it may start with
143+
`<colon> <indent>` and end with `<outdent>`.
144+
Analogous rules apply for enum bodies, type refinements, and local packages containing nested definitions.
143145

144146
With these new rules, the following constructs are all valid:
145147

@@ -170,17 +172,19 @@ In each case, the `:` at the end of line can be replaced without change of meani
170172

171173
The syntax changes allowing this are as follows:
172174

175+
Define for an arbitrary sequence of tokens or non-terminals `TS`:
176+
173177
```
174-
Template ::= InheritClauses [colonEol] [TemplateBody]
175-
EnumDef ::= id ClassConstr InheritClauses [colonEol] EnumBody
176-
Packaging ::= ‘package’ QualId [nl | colonEol] ‘{’ TopStatSeq ‘}’
177-
SimpleExpr ::=newConstrApp {‘withConstrApp} [[colonEol] TemplateBody]
178+
:<<< TS >>> ::= ‘{’ TS ‘}’
179+
| <colon> <indent" TS <outdent>
180+
```
181+
Then the grammar changes as follows:
182+
```
183+
TemplateBody ::= :<<< [SelfType] TemplateStat {semi TemplateStat} >>>
184+
EnumBody ::= :<<< [SelfType] EnumStat {semi EnumStat} >>>
185+
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>>
186+
Packaging ::= ‘package’ QualId :<<< TopStats >>>
178187
```
179-
180-
Here, `colonEol` stands for ": at end of line", as described above.
181-
The lexical analyzer is modified so that a `:` at the end of a line
182-
is reported as `colonEol` if the parser is at a point where a `colonEol` is
183-
valid as next token.
184188
185189
### Spaces vs Tabs
186190
@@ -444,15 +448,15 @@ indented regions where possible. When invoked with options `-rewrite -no-indent`
444448
The `-indent` option only works on [new-style syntax](./control-syntax.md). So to go from old-style syntax to new-style indented code one has to invoke the compiler twice, first with options `-rewrite -new-syntax`, then again with options
445449
`-rewrite -indent`. To go in the opposite direction, from indented code to old-style syntax, it's `-rewrite -no-indent`, followed by `-rewrite -old-syntax`.
446450

447-
### Variant: Indentation Marker `:`
451+
### Variant: Indentation Marker `:` for Arguments
448452

449-
Generally, the possible indentation regions coincide with those regions where braces `{...}` are also legal, no matter whether the braces enclose an expression or a set of definitions. There is one exception, though: Arguments to function can be enclosed in braces but they cannot be simply indented instead. Making indentation always significant for function arguments would be too restrictive and fragile.
453+
Generally, the possible indentation regions coincide with those regions where braces `{...}` are also legal, no matter whether the braces enclose an expression or a set of definitions. There is one exception, though: Arguments to functions can be enclosed in braces but they cannot be simply indented instead. Making indentation always significant for function arguments would be too restrictive and fragile.
450454

451455
To allow such arguments to be written without braces, a variant of the indentation scheme is implemented under language import
452456
```scala
453457
import language.experimental.fewerBraces
454458
```
455-
This variant is more contentious and less stable than the rest of the significant indentation scheme. In this variant, a colon `:` at the end of a line is also one of the possible tokens that opens an indentation region. Examples:
459+
In this variant, a `<colon>` token is also recognized where function argument would be expected. Examples:
456460

457461
```scala
458462
times(10):
@@ -462,24 +466,44 @@ times(10):
462466

463467
or
464468

469+
```scala
470+
credentials `++`:
471+
val file = Path.userHome / ".credentials"
472+
if file.exists
473+
then Seq(Credentials(file))
474+
else Seq()
475+
```
476+
477+
or
478+
465479
```scala
466480
xs.map:
467481
x =>
468482
val y = x - 1
469483
y * y
470484
```
471-
472-
The colon is usable not only for lambdas and by-name parameters, but
473-
also even for ordinary parameters:
485+
What's more, a `:` in these settings can also be followed on the same line by the parameter part and arrow of a lambda. So the last example could be compressed to this:
474486

475487
```scala
476-
credentials ++ :
477-
val file = Path.userHome / ".credentials"
478-
if file.exists
479-
then Seq(Credentials(file))
480-
else Seq()
488+
xs.map: x =>
489+
val y = x - 1
490+
y * y
491+
```
492+
and the following would also be legal:
493+
```scala
494+
xs.foldLeft: (x, y) =>
495+
x + y
481496
```
482497

483-
How does this syntax variant work? Colons at the end of lines are their own token, distinct from normal `:`.
484-
The Scala grammar is changed so that colons at end of lines are accepted at all points
485-
where an opening brace enclosing an argument is legal. Special provisions are taken so that method result types can still use a colon on the end of a line, followed by the actual type on the next.
498+
The grammar changes for this variant are as follows.
499+
500+
```
501+
SimpleExpr ::= ...
502+
| SimpleExpr ColonArgument
503+
InfixExpr ::= ...
504+
| InfixExpr id ColonArgument
505+
ColonArgument ::= colon [LambdaStart]
506+
indent (CaseClauses | Block) outdent
507+
LambdaStart ::= FunParams (‘=>|?=>’)
508+
| HkTypeParamClause=>
509+
```

docs/sidebar.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ subsection:
138138
directory: experimental
139139
index: reference/experimental/overview.md
140140
subsection:
141-
- page: reference/experimental/fewer-braces.md
142141
- page: reference/experimental/canthrow.md
143142
- page: reference/experimental/erased-defs.md
144143
- page: reference/experimental/erased-defs-spec.md

0 commit comments

Comments
 (0)