Scala Wart: Presence of comments affects program logic
See original GitHub issueOpening this issue, as suggested by Martin, to provide a place to discuss the individual warts brought up in the blog post Warts of the Scala Programming Language and the possibility of mitigating/fixing them in Dotty (and perhaps later in Scala 2.x). These are based on Scala 2.x behavior, which I understand Dotty follows closely, apologies in advance if it has already been fixed
Did you know the presence or absence of comments can affect the logic of your program?
@ object Foo{
def bar(x: Any) = println("Foo#bar(x) " + x)
def bar = println("Foo#bar")
}
defined class Foo
@ val baz = 1
baz: Int = 1
@ {
Foo bar
baz
}
Foo#bar(x) 1
@ {
Foo bar
baz
}
Foo#bar
@ {
Foo bar
// Wooo!
baz
}
Foo#bar(x) 1
@ {
Foo bar
// Wooo!
baz
}
Foo#bar
@ {
Foo bar
// Wooo!
// Hoo!
baz
}
Foo#bar(x) 1
As you can see, this code behaves differently if we have a line between
the Foo bar
and the baz
, unless that line has a line comment on it!
When there’s no newlines or the newline is filled by a comment,
Foo.bar(x: Any)
gets called, and when there’s a newline not filled by a
comment then the other overload Foo.bar
gets called.
There are other places in the language syntax where this is the case:
@ {
class X(x: Int)(y: Int)
new X(1)(2)
class Y(x: Int)
(y: Int)
new Y(1)(2)
}
defined class X
res103_1: X = $sess.cmd103$X@6a58eda9
defined class Y
res103_3: Y = $sess.cmd103$Y@136ca935
@ {
class Z(x: Int)
(y: Int)
}
cmd105.sc:3: not found: value y
val res105_1 = (y: Int)
^
Compilation Failed
@ {
class W(x: Int)
// Woohoo
(y: Int)
}
defined class W
A full listing of the places where this “comment can change behavior of newlines” can be found in the OneNLMax rule of the ScalaParse grammar. I don’t have an immediate answer for what the correct solution is here, but I’m 99.9% sure we should make it so comments like this don’t affect the semantics of a Scala program!
PostScript:
As mentioned by Sebastian on reddit, this comes down to a question of “what do you consider comments to be”, since in these cases the Scala grammar is looking for a blank line with no printable characters. Do we consider them to be “whitespace”, which case a line with comments counts as “no printable characters”, or do we consider them “things that do nothing”, in which case there’s still “something” with printable characters on the line preventing the “blank line” rule from kicking in. My personal opinion is that “treating them as whitespace” feels more natural, but I understand that’s somewhat subjective
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:10 (9 by maintainers)
Top GitHub Comments
@LPTK I like this proposal, but I think its viability depends on whether we can write a reliable rewriting rule to not break existing code.
Just wanted to add a use case for this behavior, that I find very useful. I often format mixin compositions with many traits as follows:
Then it’s very easy to comment and uncomment one of the trait as needed:
Or to document each mixin:
I’ve also left a message on the forum a while ago, with a proposal that could solve both this and the problem with postfix operators; it is copy-pasted below:
I think there’s a better solution to postfix operators, which would be to introduce some limited measure of indentation sensitivity to Scala’s syntax.
means:
and
means:
I think this will avoid confusing newcomers, since it’s a natural convention that most people already follow – that a non-indented line does not normally continue the expression above.
The same principle could be used to get rid of the fact that removing a comment in some places can break Scala code, which many people seem to find inexcusable.
means (new behavior, less surprising IMHO):
and
means:
which is the same as:
same as: