What do grave accents do/mean in Kotlin? - kotlin

In as many expressions/definitions as possible please.
I'm writing a test function, where after the call fails, the function returns:
`this `fails with` "the state is propagated"`
(with the grave accents surrounding fails with ^ i don't know how to escape, sorry)

You want to use them when something is a Kotlin keyword (like Java's System.in) but you need to call it. Then you can do
System.`in`
instead to make it work.
You can also use this in variables, functions, classes and any other identifiers. There is a small paragraph on this topic on Kotlin's documentation.

Actually, it is more than that.
You can use any class, function, variable, or identifier whose name contains spaces or symbols with grave accents.
class `Class name with spaces` {
fun `method name with spaces, +, -`(`a parameter`: Int) {
val `variable?!` = `a parameter` + 1
println(`variable?!`.toString())
}
}
fun main(args: Array<String>) {
val instance = `Class name with spaces`()
instance.`method name with spaces, +, -`(100)
}
This is a compilable and working code:
This is often used in testing, in order to make the test method names self-explanatory.
class OperationsUnitTest {
#Test
fun `addition should be commutative`() {
...
}
}

Related

Kotlin multiline-string annotation parameters

In Java, now that it supports text blocks, you can do this:
#Schema(description = """
Line one.
Line two.
""")
public void someMethodName() { ... }
In Java, text blocks are compile-time constants and they automatically remove the indents. But in Kotlin, if you do this:
#Schema(description = """
Line one.
Line two.
""")
fun someMethodName() { ... }
you end up with unwanted spaces in front of each line. Unfortunately, you can't use trimMargin() or trimIndent() because they are not compile-time constants. Is there a way to make it look as nice in Kotlin as it does in Java?
Unfortunately for your use case, I don't think so. The point of the triple quote is to provide a way to write "Formatted" text into a string. If Java doesn't behave the same way as Kotlin, then technically it's the odd one out as any other language I've used behaves the same way as Kotlin. Your best alternative would be something like the following:
#Schema(description = "Line one.\n"
+ "Line two.\n"
+ "Line three.")
fun someMethodName() { ... }
The string concatenation will be performed at compile time since it is between literals.

Why does Kotlin allow variable declarations with the same name as a parameter inside a method?

Why does Kotlin allow variable declarations with the same name as a parameter inside a method? Then also, is there any way to access the 'hidden' parameter?
For example:
fun main(args: Array<String>) {
val args = Any()
}
This is called shadowing and it is useful for decoupling your code from other parts of the system. It is possible because names are bound to the current scope.
Consider this:
You subclass a class Foo from someone else, let's say an API. In your code you introduce a variable bar. The author of Foo also updates his code and also adds a variable bar. Without the local scope, you would get a conflict.
By the way, this is also possible in other JVM bases languages including Java and commonly used within constructors or setters:
public TestClass(int value, String test) {
this.value = value;
this.test = test;
}
public void setFoo(String foo) {
this.foo = foo;
}
Shadowing does not only apply to parameters, other things can be shadowed too: fields, methods and even classes.
Most IDEs will warn you about shadowing as it can be confusing.
Recommendation for our own code:
try to avoid shadowing for two reasons:
your code becomes hard to read as two different things have the same name, which leads to confusion.
once shadowed, you can no longer access the original variable within a scope.
Kotlin does issue a warning about name shadowing which you can suppress with:
#Suppress("NAME_SHADOWING")
val args = Any()
Allowing for such shadowing may be handy in some cases e.g. throwing a custom exception after parameter validation:
fun sample(name: String?) {
#Suppress("NAME_SHADOWING")
val name = name ?: throw CustomArgumentRequiredException()
println(name.length)
}
It is unfortunately not possible to access the shadowed variable.
It is also not possible to turn a warning into an error at the moment.
Something also to note and if it isn't already realized or if anyone else new comes along. In kotlin you don't have access to the params if they are not prefixed with var/val until you add them as properties. So if a basic class was defined as this:
class Person(name: String, age: Int){
}
you can't use name or age until they are in scope; however it is unnecessary to shadow
with exceptions of desired reasons as miensol pointed out, but for the sake of being basic.
class Person(name: String, age: Int){
var name = name
var age = age
}
do these in the constructor
class Person(var name: String, private var age: Int){
}
you also will of course then have access based on the signature you gave on the object created.

final or val function parameter or in Kotlin?

Why does Kotlin removed the final or val function parameter which is very useful in Java?
fun say(val msg: String = "Hello World") {
msg = "Hello To Me" // would give an error here since msg is val
//or final
...
...
...
}
Kotlin function parameters are final. There is no val or final keyword because that's the default (and can't be changed).
After Kotlin M5.1 support of mutable parameters removed, In earlier versions that can be achieve using
fun foo(var x: Int) {
x = 5
}
According to Kotlin developers, main reasons of removing this feature are below -
The main reason is that this was confusing: people tend to think that this means passing a parameter by reference, which we do not support (it is costly at runtime).
Another source of confusion is primary constructors: “val” or “var” in a constructor declaration means something different from the same thing if a function declarations (namely, it creates a property).
Also, we all know that mutating parameters is no good style, so writing “val” or “var” infront of a parameter in a function, catch block of for-loop is no longer allowed.
Summary - All parameter values are val now. You have to introduce separate variable for re-initialising. Example -
fun say(val msg: String) {
var tempMsg = msg
if(yourConditionSatisfy) {
tempMsg = "Hello To Me"
}
}
And another reason is that val and var differ by only one letter. This can be very confusing. So for function parameters they removed the option completely. Thus eliminating the confusion in this one small area (yet keeping it everywhere else--go figure).
This decision was made to avoid fragile base class problem. It happens when a small change in base classes (superclasses) makes subclasses malfunction.

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?
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.
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.
Kotlin seems to mostly infer semicolons eagerly. There seem to be exceptions (as shown in Jayson Minard's enum example).
Generally, the type system will catch badly inferred semicolons, but here are some cases where the compiler fails.
If an invocation's arguments are in the next line (including the parenthesis), Kotlin will assume that arguments are simply a new parenthesised expression statement:
fun returnFun() : (x: Int) -> Unit {
println("foo")
return { x -> println(x) }
}
fun main(args: Array<String>) {
println("Hello, world!")
returnFun()
(1 + 2) // The returned function is not called.
}
A more common case could be the following, where we have a return with the expression in the next line. Most of the time the type system would complain that there is no return value, but if the return type is Unit, then all bets are off:
fun voidFun() : Unit {
println("void")
}
fun foo() : Unit {
if (1 == 1) return
voidFun() // Not called.
}
fun bar() : Unit {
if (1 == 1)
return
voidFun() // Not called.
}
The bar function could potentially happen, if the return voidFun() wouldn't fit on one line. That said, must developers would simply write the call to the function on a separate line.

Infix notation and with(...) does not work as I expected

Consider the following scenario:
I have a class Test
class Test() {
infix fun say(msg: String) = println(msg)
}
and a main method
fun main(args: Array<String>) {
val test = Test()
test say "Hello World!" //Works
with(test) {
say "Goodbye World!" //Does not work
say("Hello again!") //Works
}
}
As you can see I'm testing out the infix notation. Considering with(...) allows you to work with the object passed as parameter in the with block
without having to access its members through the dot notation, I would expect the infix notation to work like I show in my example above.
Unfortunately this does not work, is there a reason why this does not work? Is it a bug or simply a limitation? Or perhaps I am not interpreting the with(...) function correctly?
Infix notation is about the syntax of the way it's used. It works with an object on the left and the parameter on the right.
When using with you no longer have an object token on the left, so the special syntax for infix notation no longer works. You have to fall back to the regular function notation.
This restriction is necessary for the parser to parse the code without conflicts with other syntax.