8000 SIP-27: Major rework: multi-line, 2 variants & spec · felixmulder/scala.github.com@049df35 · GitHub
[go: up one dir, main page]

Skip to content

Commit 049df35

Browse files
committed
SIP-27: Major rework: multi-line, 2 variants & spec
1 parent d51d757 commit 049df35

File tree

1 file changed

+106
-37
lines changed

1 file changed

+106
-37
lines changed

sips/completed/_posts/2016-06-25-trailing-commas.md

Lines changed: 106 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ vote-text: The following proposal needs to be updated, since only the specialize
2525
| Sep 04th 2016 | New motivation: VCS authorship attribution |
2626
| Sep 04th 2016 | New drawback: Cross building hinderance |
2727
| Sep 12th 2016 | Remove cross building hinderance from drawbacks |
28+
| Nov 12th 2016 | Major rework: multi-line, 2 variants & spec |
2829

2930
## Motivation
3031

31-
### Easy to modify lists
32+
### Ease of modification
3233

3334
When using a comma-separated sequence of elements on multiple lines, such as:
3435

@@ -40,33 +41,33 @@ Seq(
4041
)
4142
{% endhighlight %}
4243

43-
It is quite inconvenient to remove or comment out any element because one has to think about the fact that the last element mustn't have a trailing comma:
44+
It is inconvenient to remove or comment out elements because the last element mustn't have a trailing comma:
4445

4546
{% highlight scala %}
46-
Map(
47+
Seq(
4748
foo,
48-
bar //,
49+
bar,
4950
// baz
50-
)
51+
) // error: illegal start of simple expression
5152
{% endhighlight %}
5253

53-
Secondly, it is quite inconvenient to re-order the sequence, for instance if you wanted `baz` before `bar` you need to micromanage which is followed by a comma and which isn't:
54+
It is also inconvenient to reorder because every element but the last one must be followed by a comma:
5455

5556
{% highlight scala %}
5657
val xs = Seq(
5758
foo,
58-
baz // This isn't going to work
59+
baz
5960
bar,
60-
)
61+
) // error: illegal start of simple expression
6162
{% endhighlight %}
6263

6364
### Reduce diff noise
6465

65-
Allowing trailing commas also reduces a lot of noise in diffs, such as:
66+
Adding and removing commas also introduces unnecessary noise in diffs:
6667

6768
{% highlight diff %}
6869
@@ -4,7 +4,8 @@
69-
Map(
70+
Seq(
7071
foo,
7172
bar,
7273
- baz
@@ -77,15 +78,15 @@ Allowing trailing commas also reduces a lot of noise in diffs, such as:
7778

7879
### VCS authorship attribution
7980

80-
Using the example above, the authorship of the `baz` line would be preserved, instead of becoming that of the author of the `quux` line.
81+
Using the example above, adding a comma after `baz` also unnecessarily changed the authorship of the line.
8182

8283
### Simplify code generation
8384

84-
Such a feature would also simplify generating Scala source code.
85+
Allowing trailing commas would also simplify generating Scala source code.
8586

8687
### Long standing ticket
8788

88-
There is an open ticket ([SI-4986][]) where this feature was requested, referencing the fact that it facilitates code generation by tools and allows for easier sorting of the values, initially in the context of import selectors but later also for other constructs in the syntax.
89+
([SI-4986][]) was opened in 2011 requesting support for trailing commas, referencing that it facilitates code generation by tools and allows easier sorting of values. It was initially in the context of import selectors but later also for other constructs in the syntax.
8990

9091
### Real-world use-cases
9192

@@ -96,45 +97,113 @@ Some real-world use-cases where elements of a sequence are typically added, remo
9697

9798
## Design Decisions
9899

99-
There are a number of different elements of the Scala syntax that are comma separated, but instead of changing them all a subset of the more useful ones was chosen:
100+
### Multi-line
101+
102+
It is not the intent of introducing trailing commas to promote a code style such as:
103+
104+
{% highlight scala %}
105+
val xs = Seq(foo, baz, bar, )
106+
{% endhighlight %}
107+
108+
Trailing comma support is therefore restricted to only comma-separated elements that are on separate lines:
109+
110+
{% highlight scala %}
111+
val xs = Seq(
112+
foo,
113+
baz,
114+
bar,
115+
)
116+
{% endhighlight %}
117+
118+
### What parts of the Scala grammar to change
119+
120+
There are a number of different parts of the Scala grammar that are comma-separated and, therefore, could support trailing commas. Specifically:
121+
122+
* `ArgumentExprs`
123+
* `Params` and `ClassParams`
124+
* `SimpleExpr1`
125+
* `TypeArgs`, `TypeParamClause` and `FunTypeParamClause`
126+
* `SimpleType` and `FunctionArgTypes`
127+
* `SimplePattern`
128+
* `ImportSelectors`
129+
* `Import`
130+
* `Bindings`
131+
* `ids`, `ValDcl`, `VarDcl`, `VarDef` and `PatDef`
132+
133+
With this proposal I would like to present 2 variants:
134+
135+
1. The first variant adds trailing comma support to only `ArgumentExprs`, `Params` and `ClassParams`, which I consider to be the parts of the grammar that would most benefit from trailing commas.
100136

101-
* tuples
102-
* argument and parameter groups, including for implicits, for functions, methods and constructors
103-
* import selectors
137+
2. The second variant adds trailing comma support to the whole grammar, which means more consistency, but also supporting trailing commas in places that doesn't really need it, such as `ids`.
104138

105-
From the spec these are:
139+
**NOTE:** I recommend the first variant: only add trailing comma support to `ArgumentExprs`, `Params` and `ClassParams`.
106140

107-
* SimpleExpr1, ArgumentExprs via Exprs
108-
* ParamClause, ParamClauses via Params
109-
* ClassParamClause, ClassParamClauses via ClassParams
110-
* ImportSelector
141+
See below for a summary of what changing `ArgumentExprs`, `Params` and `ClassParams` means.
111142

112-
The elements that have not changed are:
143+
#### Changing `ArgumentExprs`
113144

114-
* ValDcl, VarDcl, VarDef via ids
115-
* Type via FunctionArgTypes
116-
* SimpleType, TypeArgs via Types
117-
* Expr, ResultExpr via Bindings
118-
* SimplePattern via Patterns
119-
* TypeParamClause, FunTypeParamClause
120-
* ImportExp
121-
* PatDef
145+
**Spec change**
146+
147+
{% highlight diff %}
148+
Exprs ::= Expr {‘,’ Expr}
149+
-ArgumentExprs ::= ‘(’ [Exprs] ‘)’
150+
+ArgumentExprs ::= ‘(’ [Exprs] [‘,’] ‘)'
151+
{% endhighlight %}
152+
153+
**Example**
154+
{% highlight scala %}
155+
Seq(
156+
foo,
157+
bar,
158+
baz,
159+
)
160+
{% endhighlight %}
161+
162+
## `Params` and `ClassParams`
163+
164+
**Spec change**
165+
{% highlight diff %}
166+
Params ::= Param {‘,’ Param}
167+
- ParamClause ::= [nl] ‘(’ [Params] ‘)’
168+
-ParamClauses ::= {ParamClause} [[nl] ‘(’ ‘implicit’ Params ‘)’]
169+
+ ParamClause ::= [nl] ‘(’ [Params] [‘,’] ‘)’
170+
+ParamClauses ::= {ParamClause} [[nl] ‘(’ ‘implicit’ Params [‘,’] ‘)’]
171+
172+
ClassParams ::= ClassParam {‘,’ ClassParam}
173+
- ClassParamClause ::= [nl] ‘(’ [ClassParams] ‘)’
174+
-ClassParamClauses ::= {ClassParamClause} [[nl] ‘(’ ‘implicit’ ClassParams ‘)’]
175+
+ ClassParamClause ::= [nl] ‘(’ [ClassParams] [‘,’] ‘)’
176+
+ClassParamClauses ::= {ClassParamClause} [[nl] ‘(’ ‘implicit’ ClassParams [‘,’] ‘)’]
177+
{% endhighlight %}
178+
179+
**examples**
180+
{% highlight scala %}
181+
def bippy(
182+
foo: Int,
183+
bar: String,
184+
baz: Boolean,
185+
)
186+
187+
class Bippy(
188+
foo: Int,
189+
bar: String,
190+
baz: Boolean,
191+
)
192+
{% endhighlight %}
122193

123194
## Implementation
124195

125-
The implementation is a simple change to the parser, allowing for a trailing comma, for the groups detailed above, and has been proposed in [scala/scala#5245][].
196+
The implementation of trailing commas is a matter of changing some of the implementation of Scala's parser. An implementation of an earlier version of this proposal can be found at [scala/scala#5245][].
126197

127198
## Drawbacks/Trade-offs
128199

129-
The drawback, or trade-off, to this change is that it adds another way in which it is possible to do something in Scala. But it is the opinion of this SIP that the pragmatic advantage of being able to have trailing commas is worth this drawback.
200+
One drawback, or trade-off, to this change is that it adds an alternative way in which it is possible to do something in Scala. But I believe that the pragmatic advantage of being able to have trailing commas is worth this drawback.
130201

131-
Given that this is a change in syntax, another drawback is that it requires changing the existing tools, such as those that parse Scala: intellij-scala, scalariform, scala.meta and scalaparse.
202+
Another drawback, given this is a change in syntax, is that it requires changing the existing tools, such as those that parse Scala: intellij-scala, scalariform, scala.meta and scalaparse.
132203

133204
## Alternatives
134205

135-
As an alternative, trailing commas support could be added universally to all the comma-separated elements of the syntax. This would mean changing more (but still only in the parser), but it would make it consistent.
136-
137-
As an alternative to changing the language, there already exists today a compiler plugin called [scala-commas][] that provides this feature. It also provides some evidence that people would even use unsupported compiler apis and reflection to add this functionality, even when such a plugin won't compose with other plugins well, though arguably only weak evidence as it's a young and obscure plugin.
206+
As an alternative to changing the language, there already exists today a compiler plugin called [scala-commas][] that provides a variant of this feature. It also provides some evidence that people would even use unsupported compiler apis and reflection to add this functionality, even when such a plugin won't compose with other plugins well, though arguably only weak evidence as it's a young and obscure plugin.
138207

139208
## References
140209

0 commit comments

Comments
 (0)
0