Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the rules of semicolon inference?

Kotlin provides “semicolon inference”: syntactically, subsentences (e.g., statements, declarations etc) are separated by the pseudo-token SEMI, which stands for “semicolon or newline”. In most cases, there’s no need for semicolons in Kotlin code.

This is what the grammar page says. This seems to imply that there is a need to specify semicolons in some cases, but it doesn't specify them, and the grammar tree below doesn't exactly make this obvious. Also I have suspicions that there are some cases where this feature may not work correctly and cause problems.

So the question is when should one insert a semicolon and what are the corner cases one needs to be aware of to avoid writing erroneous code?

like image 312
Malcolm Avatar asked Sep 04 '16 15:09

Malcolm


People also ask

What are the rules of a semi colon?

Rule. Use a semicolon between closely related independent clauses which are not joined by a coordinating conjunction. This rule means that semicolons are used between two complete sentences which are not already linked by words like and, but, or, nor, for, so, yet.

What effect does a semi colon have on the reader?

The use of the semicolon suggests that the writer sees the two smaller sentences as being more closely related than the average two consecutive sentences; preferring the semicolon to and often gives a more vivid sense of the relation between the two.

When to use a semicolon in an independent clause?

Rule 1: Use a semicolon between independent clauses that are closely related in theme. Independent clause definition: a word group that contains at least one subject, at least one verb, and expresses a complete thought. An independent clause is also called a sentence.

What are semicolons in a list?

Semicolons (;) separate independent clauses that are related in meaning, and they separate items in a list when those items themselves are long or include commas. For example, this summary could say "Semicolons are useful; they show that clauses are related in meaning." What Is a Semicolon?

What does it mean when a comma becomes a semicolon?

That something can either be the right conjunction or the period that turns a comma into a semicolon. If semicolons can link independent clauses that would otherwise have a period or a conjunction between them, that means they can demonstrate contrast, too. This is part of the same rule, but the conjunction in question is “but” instead of “and.”

Can a semicolon show contrast in a sentence?

If semicolons can link independent clauses that would otherwise have a period or a conjunction between them, that means they can demonstrate contrast, too. This is part of the same rule, but the conjunction in question is “but” instead of “and.” In other words:


Video Answer


2 Answers

You only need to specify semicolons in cases where it is ambiguous to the compiler what you are trying to do, and the absence of a semicolon would result in an obvious compiler error.

The rule is: Don't worry about this and don't use semicolons at all (other than the two cases below). The compiler will tell you when you get it wrong, guaranteed. Even if you accidentally add an extra semicolon the syntax highlighting will show you it is unnecessary with a warning of "redundant semicolon".

The two common cases for semi-colons:

An enum class that has a list of enums and also properties or functions in the enum requires a ; after the enum list, for example:

enum class Things {
    ONE, TWO;

    fun isOne(): Boolean = this == ONE
}

And in this case the compiler will tell you directly if you fail to do it correctly:

Error:(y, x) Kotlin: Expecting ';' after the last enum entry or '}' to close enum class body

Otherwise the only other common case is when you are doing two statements on the same line, maybe for brevity sake:

myThingMap.forEach { val (key, value) = it; println("mapped $key to $value") } 

Absence of a semicolon in this last example will give you a more mysterious error at the point where it is confused what you are doing. It is really hard to make some code that would both be valid as two statements separated by a semicolon that are also valid when the semicolon is removed and they become one.

In the past there were other cases like an initialization block of a class which was more "anonymous" { ... } before Kotlin 1.0 and later became init { ... } which no longer needed the semicolon because it is much clearer. These cases no longer remain in the language.

Confidence in this feature:

Also I have suspicions that there are some cases where this feature may not work correctly and cause problems.

The feature works well, there is no evidence anywhere that there are problems with this feature and years of Kotlin experience have not turned up any known cases where this feature backfires. If there is a problem with a missing ; the compiler will report an error.

Searching all of my open-source Kotlin, and our internal rather large Kotlin projects, I find no semi-colons other than the cases above -- and very very few in total. Supporting the notion of "don't use semicolons in Kotlin" as the rule.

However, it is possible that you can intentionally contrive a case where the compiler doesn't report an error because you created code that is valid and has different meaning with and without a semicolon. This would look like the following (a modified version of the answer by @Ruckus):

fun whatever(msg: String, optionalFun: ()->Unit = {}): () -> Unit = ...

val doStuff: () -> Unit = when(x) {
    is String -> {
        { doStuff(x) }
    }
    else -> { 
        whatever("message") // absence or presence of semicolon changes behavior
        { doNothing() }
    }
}

In this case doStuff is being assigned the result of the call to whatever("message") { doNothing() } which is a function of type ()->Unit; and if you add a semicolon it is being assigned the function { doNothing() } which is also of type ()->Unit. So the code is valid both ways. But I have not seen something like this occur naturally since everything has to line up perfectly. The feature suggested emit keyword or ^ hat operator would have made this case impossible, and it was considered but dropped before 1.0 due to strongly opposed opinions and time constraints.

like image 187
12 revs, 2 users 99% Avatar answered Oct 23 '22 06:10

12 revs, 2 users 99%


I addition to Jayson Minard's answer, I've run into one other weird edge case where a semicolon is needed. If you are in a statement block that returns a function without using the return statement, you need a semicolon. For example:

val doStuff: () -> Unit = when(x) {
    is String -> {
        { doStuff(x) }
    }
    else -> { 
        println("This is the alternate");  // Semicolon needed here
        { doNothing() }
    }
}

Without the semicolon, Kotlin thinks the { doNothing() } statement is a second argument to println() and the compiler reports an error.

like image 31
Ruckus T-Boom Avatar answered Oct 23 '22 07:10

Ruckus T-Boom