How does `use` propagate its return value, and how do you correctly handle two resources (e.g. an input and an output stream) with `use`?
answer
- use returns the block's last expression
- nest use-in-use for two resources
- inner closes first, then outer
- don't open both before the first use
- non-local return still closes (inline)
basics
~10 suse returns whatever its lambda returns, so you can assign it directly. For two resources, nest one use inside another so both close in the right order.
solid answer
~40 s`use` is generic in its return type `R`: the value of the lambda's last expression becomes the value of the `use` call, so `val data = stream.use { it.readBytes() }` works without a separate variable. For multiple resources you nest: open the outer one with `use`, and inside its block open the inner one with another `use`. The inner resource closes first (when its block ends), then the outer, mirroring the reverse-acquisition order of Java's try-with-resources. Because `use` is `inline`, a non-local `return` inside the block returns from the enclosing function and still triggers `close()` via the finally. Avoid opening both resources before the first `use` (e.g. on one line), because if the second open throws, the first is never wrapped and leaks.
code
kotlin · 6 linesfun copy(src: File, dst: File) =
src.inputStream().use { input ->
dst.outputStream().use { output ->
input.copyTo(output)
}
}go deeper
Knows use returns a value and that you can put two use calls together for two resources.
Writes correct nested use and explains return-value propagation and close ordering.
Articulates the leak risk of opening resources outside use and the inline non-local-return behaviour.
Sets a codebase convention (e.g. lint rule) for nested-use acquisition order and reviews resource-handling APIs for it.
## Return value `use` is declared `fun <T : Closeable?, R> T.use(block: (T) -> R): R`. The type parameter `R` is the lambda's result type, so the value of the **last expression** in the block is returned by `use`: ```kotlin val bytes: ByteArray = File("img.png").inputStream().use { it.readBytes() } ``` No intermediate variable for the stream is needed, and the stream is already closed by the time `bytes` is assigned. ## Nesting two resources The correct pattern is to nest, so each resource has its own `use` and its own finally: ```kotlin File("in.txt").inputStream().use { input -> File("out.txt").outputStream().use { output -> input.copyTo(output) } } ``` - The **inner** `use` (`output`) closes first, when the inner block ends. - The **outer** `use` (`input`) closes second. - This reverse order matches Java's try-with-resources and is what you want: you finish writing/flushing the output before tearing down the input. ## Why not open both up front This is subtly wrong: ```kotlin // risky val input = File("in.txt").inputStream() val output = File("out.txt").outputStream() // if THIS throws, input leaks input.use { output.use { input.copyTo(output) } } ``` If the second `inputStream()`/`outputStream()` constructor throws, the first resource was acquired but never entered a `use`, so it leaks. Nesting acquires each resource **inside** the protection of the previous `use`. ## Inline and non-local return Because `use` is `inline`, the lambda is not a separate function. A `return` inside it returns from the **enclosing** function, and the finally still runs `close()` first: ```kotlin fun firstNonBlank(file: File): String? = file.bufferedReader().use { r -> for (line in r.lineSequence()) if (line.isNotBlank()) return line // closes r, then returns null } ``` ## Returning the resource itself is a bug Never do `socket.use { it }` to "get the resource out" — it is closed by the time `use` returns, so you would hold a dead handle.
- In nested `use`, which resource closes first and why does it matter?The innermost one. For copy/streaming you must finish and flush the output (inner) before closing the input (outer), matching try-with-resources reverse order.
- Can you `return` out of the enclosing function from inside a `use` block?Yes — `use` is inline, so a non-local return works and the resource is still closed by the finally before control leaves.
saying these in an interview costs you the question
- Opens both resources on separate lines before any `use`, leaking on failure
- Thinks you cannot return a value from `use`
- Returns the resource itself from the block and uses it afterwards
- Believes nesting closes the outer resource first
- Adds a try/finally inside the `use` block, duplicating its job