Language design

More changes: Enum Syntax, Another Deprecation and More

Enum Syntax

Currently the syntax for enums with non-trivial constructors is kind of monstrous:

enum class Message(val str: String) {
    ERROR : Message("This is an error")
    WARNING : Message("This is a friendly warning")
    DEBUG : Message("Ignore this")
}

We would really like to make it nicer, e.g. something like this:

enum class Message(val str: String) {
    ERROR("This is an error")
    WARNING("This is a friendly warning")
    DEBUG("Ignore this")
}

Now, there are some technicalities, namely, enums can have other members:

enum class Example(...) {
    A(...)
    B(...)

    fun foo() { ... }
}

The problem is that A and B can be parsed as annotations on foo(). So, we had some options to consider here.

We are leaning toward putting a separator there between entries and other members:

enum class Example(...) {
    A(...)
    B(...)
    ; // this is mandatory

    fun foo() { ... }
}

The semicolon is only necessary when some members follow it.

Other options include requiring escaping on all annotations on members (and, possibly, modifiers too):

enum class Example(...) {
    A(...)
    B(...)

    @inject fun foo() { ... }
}

This would be a little inconsistent with normal classes, traits etc.

Or we could prefix enum entries with a (soft-)keyword:

enum class Example {
    entry A
    entry B
}

This looks too verbose.

Another question here is how do we annotate enum entries themselves. Requiring escaping looks reasonable here:

enum class Example {
    @Ann1 A
    @Ann2(...) B    
}

Other options include

  • requiring a comma between enum literals (like in Java)
  • requiring a newline between enum literals and allowing unescaped annotations on the same line

We have not decided which way to go on this one yet.

Prohibiting break/continue in when-expressions

We are planning to implement continue in when-expressions as a jump to the next when-entry. It is not implemented yet, but we want your code to stay unchanged when we add it, so for the time being, we prohibit using continue in when without a label that points to a loop:

loop@
for (...) {
    when (...) {
        ... -> if (...) continue@loop else ... // OK
        ... -> if (...) continue // ERROR
    }
}

We also prohibit unlabeled break inside when. While it is not decided whether we want to allow it ever, it seems like a better design to keep break and continue symmetric.

NOTE: A simple interpretation of break inside when is “stop matching and jump outside” (as in switch in Java and C), but our when often returns a value, and that would be unknown if we break out of it.

Rename traits to interfaces

Well, we picked the names long time ago, and now what we call “trait” in Kotlin is not so much of a trait, and is exactly like Java’s interface nowadays, so we want to deprecate the usage of the trait keyword, and introduce interface in M12.

Feedback request: Let the flame begin :)

image description