So, between `{}`, a line break can imply `;`, righ...
# getting-started
r
So, between
{}
, a line break can imply
;
, right? Could we get that between
()
, a line break can imply
,
? This feels like an oversight, especially with functional programming becomming more popular, where code tends to be more nested expressions, less sequential statements. The way it is, commas feel like the new semicolons.
4
s
Interesting suggestion... my gut reaction was against, but I think I could be persuaded. I take it you're only thinking of argument/parameter lists, not parentheses forming part of an expression.
r
I’m not sure I understand, which expression would have commas in it?
s
They wouldn't, that's my point 😄. I'm just clarifying that this
Copy code
val a = (b +
  c)
obviously shouldn't imply a comma, while this
Copy code
val a = listOf(b
  c)
could
r
Yes, exactly! I honestly thought it would be coming when trailing commas were introduced (Which are so much like trailing semicolons).
e
breaks existing code which does
Copy code
(
a
or
b
)
s
actually, trailing semicolons are about writing more semicolons (not less). when you add a parameter to e.g. this constructor: val x = X( a, b, ) which will then look like this: val x = X( a, b, c, ) then the git change-set will only highlight the line with "c," since the line with "b," already contained a comma and therefore didn't have to change.
r
@Stephan Schröder Yes, exactly how trailing semicolons are about writing more semicolons (instead of just using them as statement separators), so that you don’t get a git change on the previously last statement line.
s
*not semicolons, commas!
so why you you assume a change to write more commas would be followed by a change to write fewer commas?
r
Because the change to write more semicolons ended up in fewer semicolons. Some old languages don’t have trailing semicolons, only separating semicolons, like what we had with commas until recently.
s
again, commas, not semicolons
e
semicolon omission was always in the language so it doesn't break anything now (although it definitely breaks some people's coding habits, like braces on separate lines)
plus1 1
comma omission would definitely break things
r
Semicolon history:
Copy code
{
  a;
  b;
  c
}
{
  a;
  b;
  c;
}
{
  a
  b
  c
}
Comma history:
Copy code
(
  a,
  b,
  c
)
(
  a,
  b,
  c,
)
???
Alright, maybe in the next language then 🤷
s
no, Kotlin never had obligatory semicolons at the end. And the first example with no semicolons at the last one I only know from Rust, where it means "return"
the only time I use a semicolon in Kotlin is when writing enums.
e
semicolon was a delimiter instead of a terminator in Awk, so it is possible to write blocks in the 1st style in Perl and Ruby too. and it ends up allowed as a side effect of Javascript's semicolon insertion rules too. but no other C-like language I know of has that behavior
(like Stephan says,
{ a; b }
means
{ a; return b; }
in Rust, so it's not the same)
k
Many languages feature statements that are terminated by newline, starting from the 1960s: Fortran, Basic, Python, Haskell, and many others. Kotlin's optional semicolon is no pioneer. On the other hand, I know of no language at all that allows comma omission.
r
@Klitos Kyriacou Kinda Lisp and Haskell. Haskell even allows omitting ().
h
> comma omission would definitely break things What would it break? Just like with semicolons, not every newline should trigger a semicolon/comma, only when it's syntactically correct to insert one. The only thing I can think of where both inserting and not inserting a comma would be syntactically correct has an analogous case with semicolons: an optional trailing lambda argument on a line of its own:
Copy code
fun f(a: Int, lambda: () -> Int = { 42 }): Int = 0

val x = f(1) // auto-insert semicolon? (Kotlin doesn't do this)
    { 2 }

val y = f(
    f(1) // auto-insert comma?
    { 2 }
)
I'd like to know why it's a bad idea because it feels like a bad idea, but I can't figure out why.
💡 1
m
Pretty sure it would break infix notation for example
k
> @Klitos Kyriacou Kinda Lisp and Haskell. Haskell even allows omitting (). Haskell uses juxtaposition for function application, and functions are curried, so it's a different thing than omitted parentheses/commas. Lisp uses lists to specify functions and parameters together in the same list, and lists have always and only been space-separated, it's not a matter of omitted commas.
h
> Pretty sure it would break infix notation for example How..? I can't think of an example where the current semicolon strategy doesn't also break, and clearly that hasn't been an issue.
Copy code
println(
    1 // shouldn't insert a comma here
    shl 2
)

val x = 1
    shl 2 // fails, semi colon inserted at line above
e
@Huib Donkers
Copy code
val a = 1
val b = 0
val or = 2
val list = listOf(
    a
    or
    b
) // [3] or [1, 0, 2]
gratitude thank you 2
👏 4
☝️ 1
h
Definitely extremely confusing to allow omitting commas there. Technically, semicolons have the same issue, but somehow it feels like less of a problem:
Copy code
val or = 0
val x =
1
or
2

// result: x == 1
e
it's not a change in behavior since semicolons have always been optional
👍 1
> Kinda Lisp and Haskell. Haskell even allows omitting (). ?? Lisp s-exprs aren't comma-optional, they're no-comma. delimiter commas in Haskell lists and tuples aren't optional, only the trailing one is.
it does have the ML-like function application which doesn't require parentheses, but (syntactically) it only allows a single argument and everything else is currying
c
This would change the meaning of this code:
Copy code
val a = foo(
    5
    +2
)
Currently,
foo(5+2)
, but this proposal would make it
foo(5, +2)
.
☝️ 3
e
simpler version of my example, yeah. there's other constructs that would be interpreted differently, such as
Copy code
foo(
    bar.let
    { it }
)