1

I encountered the strangest thing.

Lets say I have a text file called "lines.txt". This file contains lines in key value pairs.

test:100
test1:200
test2:300
test3:400

If I read this file in Kotlin the list is not empty however the loop inside the output stream does not get called.

object App {

@JvmStatic
fun main(args: Array<String>) {

    // file containing lines of text
    val lines = Files.readAllLines(Paths.get("./hashes.txt"))

    // not empty
    println(lines.size)

    // write back a modified version
    PrintWriter(FileWriter(File("./lines2.txt"))).use { out -> {

            // this doesn't get called
            println(lines.size)
            lines.forEach {
                out.println(it.split(":")[0])
            }

        }
    }

}

}

I don't understand why this is so if anyone can enlighten me that would be awesome.

2 Answers 2

2

The list is not empty. A single println(lines.size) will shown you that, because that println is never called.

You simply have one pair of curly braces too much.

change your code to

   ...
   PrintWriter(FileWriter(File("./lines2.txt"))).use { out ->

        // list is empty??
        println(lines.size)
        lines.forEach {
            out.println(it.split(":")[0])
        }
    }
    ...

The reason is, that a lambda doesn't need its block in curly braces.

So don't write

out -> { ... }

just write

out -> ...
Sign up to request clarification or add additional context in comments.

Comments

2

guenther already told you what is wrong with your code, but I think an explanation of what happened is missing.

Consider the following:

val x = { println("y") }

Will it print out y? No, the lamda is never invoked. You have to call x().

Let's take a look at what you did:

val x = { { println("y") } }
x()

Will it print out y? No, because you don't invoke the lambda that prints y.

To make things more clear, let's specify the types explicitely.

val x:() -> (() -> Unit) = { { println("y") } }

Now we can see that the first lambda invoked by x() returns a lambda as well so you would have to call x()() in order to invoke the returned lambda as well.

So using a second pair a curly braces is not just not optional but gives the code a whole new meaning.


But this means that there would be also another solution to your problem.

PrintWriter(FileWriter(File("./lines2.txt"))).use { out -> {
        println(lines.size)
        lines.forEach {
            out.println(it.split(":")[0])
        }
    }() // <-- add braces here to invoke the lambda
}

So, you can either remove two brackets are add two more. Choice is yours.

Disclaimer: Removing two braces is the way to go. The other option is just to prove a point.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.