I am getting error for this syntax
for (i in 0 until 8) {
for (j in 0 until 8) {
} println()
}
error is
For is not an expression, and only expressions are allowed here.
but this is valid
for (i in 0 until 8) {
for (j in 0 until 8) {
}
println()
}
only thing I changed was where println() is called, I have worked with java so I thought that placement should not matter. What is the issue here ?
I did some testing in Kotlin Playground. Kotlin compiler indeed cannot parse statements that are placed on the same line and not divided by ;.
For example 10 println("")
will produce an error: "Unresolved reference: println".
Note that 10 actually is an expression, since expressions are code blocks that produce single value.
The guessing is below:
The real question is, why Kotlin compiler shows the specific error, which is
For is not an expression, and only expressions are allowed here
I believe that has something to do with the Kotlin compiler's code parse algorithm. That seems like compiler tries to parse multiple statements on the same line as a single expression. for keyword makes it fail right away. However, if you replace for loop with a real expression, compiler will highlight the println call as something wrong, since it is something excess for an expression.
Related
I found this code in a Kotlin library and I couldn't find any information on it.
open fun <Type : ScreenType> addScreen(type: Class<Type>, screen: Type) {
!screens.containsKey(type) || throw GdxRuntimeException("Screen already
registered to type: $type.")
screens.put(type, screen)
}
I don't understand the middle part. What is that strange "OR" operator doing there?
In Kotlin, throwing an Exception evaluates as an expression that returns Nothing. Nothing is treated like a sub-type of anything else, so that first line of code is basically an expression of type Boolean || Nothing, which can be simplified to just Boolean. Kotlin also allows a line of code to simply be an expression (many other languages like Java do not), so you can simply put this line of code to evaluate the two parts of the expression sequentially, and the throw will be skipped (short-circuited) if the first part of the expression is true.
While writing code like this in Kotlin is possible, it is certainly not idiomatic. In my opinion, it is unclear for readability. The equivalent behavior can be achieved with code that very clearly shows its intent:
if (screens.containsKey(type)) {
throw GdxRuntimeException("Screen already registered to type: $type.")
}
The expression uses short-circuiting property of the OR operator. The right-hand side is only evaluated if the left-hand side is false. That way it's just another way to write conditional code.
Let's assume that I have two functions which do the same stuff.
First one:
fun doSomething() = someObject.getSomeData()
Second one:
fun doSomething(): SomeData {
return someObject.getSomeData()
}
Are there any technical differences between expression functions and standard function in Kotlin excluding the way how they look?
Is compiled output the same?
Are there any advantages using one instead another?
As #Sơn Phan says, they both compile to exactly the same bytecode.
So the differences are simply about conciseness. The expression form omits the braces and return; it also lets you omit the return type (using type inference as needed). As the question illustrates, the expression form can be shorter — and when all else is equal, shorter tends to be easier to read and understand.
So whether the expression form is appropriate is usually a matter of style rather than correctness. For example, this function could be on one line:
fun String.toPositiveIntegers() = split(",").mapNotNull{ it.toIntOrNull() }.filter{ it >= 0 }
But it's a bit long, and probably better to split it. You could keep the expression form:
fun String.toPositiveIntegers()
= split(",")
.mapNotNull{ it.toIntOrNull() }
.filter{ it >= 0 }
Or use a traditional function form:
fun String.toPositiveIntegers(): List<Int> {
return split(",")
.mapNotNull{ it.toIntOrNull() }
.filter{ it >= 0 }
}
(I tend to prefer the former, but there are arguments both ways.)
Similarly, I rather like using it when the body is a simple lambda, e.g.:
fun createMyObject() = MyObject.apply {
someConfig(someField)
someOtherConfig()
}
…but I expect some folk wouldn't.
One gotcha when using the expression form is the type inference. Generally speaking, in Kotlin it's good to let the compiler figure out the type when it can; but for function return values, that's not always such a good idea. For example:
fun myFun(): String = someProperty.someFunction()
will give a compilation error if the someFunction() is ever changed to return something other than a String — even a nullable String?. However:
fun myFun() = someProperty.someFunction()
…would NOT give a compilation error; it would silently change the function's return type. That can mask bugs, or make them harder to find. (It's not a very common problem, but I've hit it myself.) So you might consider specifying the return type, even though you don't need to, whenever there's a risk of it changing.
One particular case of this is when calling a Java function which doesn't have an annotation specifying its nullability. Kotlin will treat the result as a ‘platform type’ (which means it can't tell whether it's nullable); returning such a platform type is rarely a good idea, and IntelliJ has a warning suggesting that you specify the return type explicitly.
1. Compiled output
Yes the compiled output will be completely the same
2. Advantage
You usually use expression function when the body of a function is only one line of expression to make it a oneliner function. Its advantage mainly about making the code more concise. Imagine instead of all the brackets and return, you only need a = to make things done.
The below code
fun main(args: Array<String>) {
println("Enter your value : ")
try{
val(a, b, c) = readLine()!!.split(' ')
println("Values are $a $b and $c")
}catch(ex : IndexOutOfBoundsException){
println("Invalid. Missing values")
}
}
produces the following error in Kotlin Playground:
Enter your value:
Exception in thread "main" kotlin.KotlinNullPointerException at FileKt.main(File.kt:4)
I have seen other questions with NullPointerException but I am unable to resolve it. I might would have missed some so it would be really helpful if you can share useful links. Since I am new to Kotlin, it would be awesome if you correct my program.
Remark: I don't have any background on java either and most of the NullPointerException questions are based on java
Edit 1 : I have tried gidds' solution and it seems to be working except one minor fault. The readLine() is for some reason not working.
The below code
fun main(args : Array <String>){
val line = readLine()
try{
println("Output : $line")
if (line != null) {
val(a, b, c) = line.split(' ')
println("Values are $a $b and $c")
} else {
println("No values given...")
}
}
catch(ex : IndexOutOfBoundsException){
println("Invalid. Missing Values...")
}
}
produces the following error in Kotlin Playground :
Output : null
No values given...
I guess I was getting the previous errors due to the same reason, i.e. readLine() was not working properly and the user is not getting an opportunity to give input(s).
With readLine()!!, you are saying the compiler that if this returns null, that will crash with NullPointerException. In another way, you must be sure to have return value of readLine() to be not null. Read more about !! operator here.
The not-null assertion operator (!!) converts any value to a non-null
type and throws an exception if the value is null.
You can have null check with elvis operator like below:
try{
val(a, b, c) = readLine()?.split(' ')
println("Values are $a $b and $c")
}catch(ex : IndexOutOfBoundsException){
println("Invalid. Missing values")
}
To expand on the earlier answer, this is about how to handle nulls.
The problem is that readLine() can return null. (This happens if end-of-file is reached; for example, if you redirect the input from a file, and reach the end of the file; or if it's taking input from the keyboard and you press Ctrl+D.)
The Kotlin compiler knows this. (Nullability is built into Kotlin's type system. readLine() returns a String? — the question mark indicates that the value could be null.)
Kotlin is very careful about null-safety, and won't let you do anything with the value that would fail if it's null. So in your code, if you omit the !!, you get an error on the following .. (‘Only safe (?.) or non-null asserted (!!.) calls are allowed on a non-nullable receiver of type String?’)
So you have to handle the null somehow.
Appending the not-null assertion !! effectively promises the compiler that you know better, and that it can never be null. This is usually a bad idea (which is why that operator was designed to look ugly); in practice, you generally don't know better than the compiler, and it will trip you up — as you've discovered! In your case readLine() did return null, and so the !! operator threw a KotlinNullPointerException.
So, you need a better way to handle it.
The traditional way is an explicit check, e.g.:
val line = readLine()
if (line != null) {
// Within this block, the compiler knows that line
// cannot be null.
} else {
println("No values given.")
}
This is a good, clear, general approach. And it may be the best approach in your case. (You'd still need to catch the IndexOutOfBoundsException, though.)
Because that approach can be a bit long-winded, Kotlin has some other tools that can be better in particular situations. I don't think any are appropriate here, but I'll mention some for completeness:
One of those is the safe-call operator ?. given in the error message and the earlier answer. This makes the call only if the value is not null; otherwise, it returns the null directly. That can be really useful, but it's not a simple answer in this case, as your comment shows: although it avoids trying to split() the null, you then fail to deconstruct it into the three values a, b, and c. (After all, null is not an array.)
If you wanted to substitute default values for a, b, and c if there was no input, you could use the safe-call operator in conjunction with the elvis operator ?:. That returns the left-hand side if it's not null, else the right-hand side. So you could do e.g.:
val (a, b, c) = readLine()?.split(' ')
?: arrayOf("defA", "defB", "defC")
println("Values are $a, $b, and $c.")
In this case, if readLine() returns a string, split() would be called on it; or if not, it would use the hard-coded array instead.
Note that this still isn't a complete solution, as it won't cope if you enter a line with less than two spaces. (So you'd still need to catch the IndexOutOfBoundsException, or check for that case explicitly.)
(Perhaps the shortest solution overall would be to leave the !! intact, and change the catch block to catch Exception, so it would catch the KotlinNullPointerException along with the IndexOutOfBoundsException. I'm not recommending that, as it's ugly: it's not clear to anyone reading the code what could happen and what exceptions you're intending to catch — and it could hide other problems in the code if they also resulted in exceptions.)
I found this Rust code for getting a line from stdin:
use std::io;
fn main() {
let mut line = String::new();
io::stdin().read_line(&mut line).unwrap();
println!("Input: {}", line);
}
io::stdin().read_line(&mut line) sets the line variable to a line read from stdin. From my understanding, read_line() returns a Result value, which can be pattern-matched, or .unwrap() can be used to get the inner value if it is not an Err.
However, the returned value of read_line() is never used. Only the line string variable is used, but people use .unwrap() most of the time even if it is not used.
What is the purpose of unwrap() if the returned value is not used? Just to throw an error?
What is the purpose of unwrap() if the returned value is not used? Just to throw an error?
Yes, but that's not all.
Ignoring potential errors is bad; there's a big difference between an empty line and a line that's not been read because of an error; for example in a typical "pipeline" command in a shell, the program needs to stop when it stops receiving input, otherwise the user has to kill it.
In C, ignoring errors is too easy. Many languages solve this by having exceptions, but Rust doesn't.
In order to avoid the issue plaguing C programs that it's too easy to forget to check the return code, normally Rust functions will bundle the expected return value and error in Result, so that you have to check it to get the return value.
There is one potential issue left, however: what if the caller doesn't care about the return value? Most notably, when the value is (), nobody really cares about it.
There is a bit of compiler magic invoked here: the Result structure is tagged with the #[must_use] attribute. This attribute makes it mandatory to do something with Result when it's returned.
Therefore, in your case, not only is unwrapping good, it's also the simplest way to "do something" and avoid a compilation warning.
If you don't want to "elegantly" handle cases where there is a failure to read a line from stdin (e.g. by attempting it once again or picking a default value), you can use unwrap() to trigger a panic; it silences the warning caused by a Result that is not used:
warning: unused result which must be used
--> src/main.rs:5:5
|
5 | io::stdin().read_line(&mut line);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_must_use)] on by default
This question already has answers here:
Why can't variables be declared in a switch statement?
(23 answers)
Closed 9 years ago.
I saw a few answers to this issue, and I get it — you can't declare and assign variables inside a switch. But I'm wondering if the following is correct at throwing an error saying
error: expected expression before 'int'
Code:
switch (i) {
case 0:
int j = 1;
break;
}
Why would putting a call to NSLog() before it result in no errors?
switch (i) {
case 0:
NSLog(#"wtf");
int j = 1;
break;
}
You actually can declare variables within a switch if you do it according to the syntax of the language. You're getting an error because "case 0:" is a label, and in C it's illegal to have a declaration as the first statement after a label — note that the compiler expects an expression, such as a method call, normal assignment, etc. (Bizarre though it may be, that's the rule.)
When you put the NSLog() first, you avoided this limitation. You can enclose the contents of a case in { } braces to introduce a scoping block, or you can move the variable declaration outside the switch. Which you choose is a matter of personal preference. Just be aware that a variable declared in { } braces is only valid within that scope, so any other code that uses it must also appear within those braces.
Edit:
By the way, this quirk isn't as uncommon as you might think. In C and Java, it's also illegal to use a local variable declaration as the lone statement (meaning "not surrounded by braces) in a for, while, or do loop, or even in if and else clauses. (In fact, this is covered in puzzler #55 of "Java Puzzlers", which I highly recommend.) I think we generally don't write such errors to begin with because it makes little sense to declare a variable as the only statement in such contexts. With switch / case constructs, though, some people omit the braces since the break statement is the critical statement for control flow.
To see the compiler throw fits, copy this horrific, pointless snippet into your (Objective-)C code:
if (1)
int i;
else
int i;
for (int answer = 1; answer <= 42; answer ++)
int i;
while (1)
int i;
do
int i;
while (1);
Yet another reason to always use { } braces to delimit the body of such constructs. :-)
I've run into this issue before, and the conclusion was that you just put the code inside a block.
switch (i) {
case 0:
{
int j = 1;
break;
}
}
Another simple workaround I use is to add an empty expression (semicolon) before the declaration. This avoids limiting the variable scope to a code block (or having some case statements with code blocks and some without).
switch (i) {
case 0:;
int j = 1;
break;
}