The state of then


#1

There’s a table reserved for the keyword then since Scala 2.10, and I am wondering if any party is going to show up.

In other languages

In ALGOL 60 and Pascal if statements are written like this:

if foo < 0 then
begin
  WriteLine('gaa');
end;

Not sure how far the use of then goes back, but we can see the remnant in ML family of languages like SML, OCaml, F#, and Haskell. Here’s F#:

if x < 0 then
  printfn "neg"
else
  printfn "non-neg"

In Scala

There’s been multiple attempts at introducing Pascal/ML style if expression to Scala.

In 2011, SIP-12 Uncluttering Scala’s syntax for control structures was proposed by Martin.

  1. Introduce a new keyword, then .

  2. Allow the following alternative syntax form:

    if expression then expression [else expression]
    
  3. At some point in the future (there’s no rush) we could deprecate the form

    if (expression) expression else expression
    

In August 2016, SIP committee unanimously rejected SIP-12.

(Edit) I originally linked to Consider syntax with significant indentation here, but now I see that if-then had been in already at that point.

The state of then

As it stands, in Scala 2.13.0-M3 REPL no longer warns about then:

scala> val then = 1
then: Int = 1

but it does for compilation:

[warn] /Hello.scala:18: then is a reserved word (since 2.10.0); usage as an identifier is deprecated
[warn] object Test { val then = 1 }
[warn]                   ^
[warn] one warning found

(Edit) Dotty implements Pascal/ML style if-then

scala> if 1 > 0 then println("bar")
bar
scala> if 1 > 0 then {
         println("foo")
       }
foo

so it takes harder stance on then used as an identifier.

[error] -- [E032] Syntax Error: /Hello.scala:18:18
[error] 18 |object Test { val then = 1 }
[error]    |                  ^^^^
[error]    |                  illegal start of simple pattern
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 3 s, completed Feb 26, 2018 10:56:14 PM

As a former Delphi programmer, I am more than happy to include then into the Scala language. If Dotty’s then is a thing, I would propose to add it to the list of reserved word in Scala Language Spec, and forbid its use as an identifier under -Xsource:2.14 flag.

Otherwise, we should remove both the warning in 2.13 and the error in Dotty. Then. Or then not.


Pre-SIP: Virtualization (feedback needed)
#2

I thought it was implemented in Dotty?


#3

You are right. This works in Dotty:

scala> if 1 > 0 then println("bar")
bar
scala> if 1 > 0 then {
         println("foo")
       }
foo

#4

My thought is to make it a reserved word, to keep Scala 2 more consistent with Dotty


#5

I don’t really see how you can unanimously reject SIP-12 and then eventually add it anyway…


#6

If you read the minutes:
http://docs.scala-lang.org/sips/minutes/2016-08-16-sip-10th-august-minutes.html#discussion-of-sip-12-uncluttering-scalas-syntax-for-control-structures

The original proposer[,] Martin Odersky[,] is not present


#7

There would need to be a new SIP, or a champion willing to revive the older SIP based on new elements since the rejection.

In any case, I would still be against it, as it introduces a second way to write things for no good reason whatsoever (and I am a Delphi fan). The only reason that was supposed to justify it was the completely alternative syntax based on indentation that Martin came up with at some point. In that context it was necessary. But I am also against that indentation based syntax, for exactly the same reason.


#8

Why was it added to Dotty without discussion?


#9

Dotty’s parser is based on this 2013 commit (https://github.com/lampepfl/dotty/commit/214eb8b650a86d1708b1257f89f53840a121de62) that was written while SIP-12 was still alive.


#10

So really, it should be removed from Dotty unless SIP-12 gets resurrected and approved?

It seems weird that the meeting was had without the proposer present.


#11

In Scala there are so much things that can be written in several ways (and in Dotty there are even more), so such claim sounds weird; especially on such a minor chage.


I feel that both variants have its own niche.

Java-styled variant looks better when condition expression is short.

if (sc) expression1 else expression2

ML-styled expression looks much better when condition expression is large or when it ends with a lot of parentheses. One more paren from if does not add any clarity, thus then variant looks better.

if foo.bar.what(ever, (tupled, f(g(5)))) then 0 else expr2

#12

I’m personally in favour of keeping this form.

The opposition, as I recall, was that it was too big a change to just add to the language, and that it would cause real problems for cross-compilation.

But… We’re talking dotty here, a.k.a scala 3.0, where a lot of other big changes that wouldn’t play nicely with cross-compilation are also happening. If the change is going to be introduced then that’s the right time to do it!

Syntactically, it enables a more literate style of programming, and removes the inconsistency where conditionals need parentheses when following if, but not in a pattern match. Both of these are desirable properties.


#13

I no longer care if “scala” from Mitteleuropa supports if-then syntax, because typelevel have taught us that we can use our fork without dire consequences.

Although I learned to code in C, I also learned that dropping parens around the if condition is so pretty. We fell in love with the case guard.

I hope “standard” scala steps up to support Beauty, Truth and the Good in syntax.

I guess Beauty happens at parser, Truth at typer and the Good at erasure.


#14

I hope “standard” scala steps up to support Beauty, Truth and the Good in syntax.

I guess Beauty happens at parser, Truth at typer and the Good at erasure.

You said it. This is about beauty. It also makes it difficult to have discussions around this topic.


#15

Here are other languages without of parenthesis around if statements. Note that not all languages provide conditional expression with if, but we can see that parenthesis-less if syntax beyond the functional ML family of languages.

BASIC

IF HUNGER > 0 THEN
  PRINT "Let them eat brioche"
END IF

Python

if 0 == n:
  print('no hits')
else:
  print(str(n) + ' hits')

Ruby

if n == 0
  puts "no hits"
else
  puts "#{n} hits"
end

Rust

if i > 0 {
  n = 1
} else {
  n = -1
}

Swift

if i > 0 {
  n = 1
} else {
  n = -1
}

F#

if x < 0 then
  printfn "neg"
else
  printfn "non-neg"

#16

Changes in Dotty are not subject to SIPs, SIPs only cover Scala 2. Dotty is still going through some phase of experimentation of how to do things better, so it’s only reasonable that every change doesn’t require acceptance from a strict review process.

Before the meeting, I had a discussion with Martin in which he was in favor of rejecting the SIP and rethink the changes in the future. That being said, there have been several cases in which the meetings have taken place without the proposer present; there is no clause in our SIP specification that prevents this from happening. So long as there is a quorum, the meeting takes place.


#17

I support making then a reserved keyword in Scala-2.12. The parentheses-less version of if is already present in pattern guards, so this is not totally inconsistent.


#18

So we have if no_parens for pattern guards, if (parens) and if no_parens then. Too much confusion for me.


#19

sorry to bikeshed, but I’d also like no parens on if, so I’d like to keep dotty’s approach and even see it in 2.13


#20

Replacing if-plus-parentheses with if-then makes conditional syntax
inconsistent with while loops and for loops. Sorry, I meant to say for
comprehensions.

Those languages that have if-then usually have while-do and for-do or
equivalent.

If you are so much pained by the inconsistencies of if conditionals with
parentheses and match guards without, just add parentheses to your match
guards and it will all look consistent. :wink: