Predict the output: a default argument that allocates a fresh list
The function below takes a list with a default value and appends one element to it. It is called three times: twice without the second argument, and once with a list the caller already owns.
Constraints: reason from the language rules only — no reflection, no library tricks. State exactly what each of the three println calls prints, and justify each line.
fun collect(item: String, into: MutableList<String> = mutableListOf()): MutableList<String> {
into.add(item)
return into
}
fun main() {
println(collect("a"))
println(collect("b"))
val shared = mutableListOf("x")
println(collect("c", shared))
}
Determine the output and explain why.
It prints [a], then [b], then [x, c]. A default value is an expression evaluated afresh on every call that omits the argument, so each defaulted call builds its own list. Passing shared explicitly appends to that list instead.
- ✗Carrying over Python's habit of a default argument evaluated once at definition
- ✗Assuming an argument passed explicitly is copied rather than shared
- ✗Believing a default value must be a constant, not an arbitrary expression
- →May a default value refer to an earlier parameter of the same function?
- →What happens to the defaults when the function is called from Java?
Output
[a]
[b]
[x, c]
Why
A Kotlin default value is an expression, not a constant, and it is evaluated afresh on every call that omits the argument. There is no single list belonging to the function.
fun collect(item: String, into: MutableList<String> = mutableListOf()): MutableList<String> {
into.add(item)
return into
}
collect("a") // into = a brand-new list → [a]
collect("b") // into = another brand-new list → [b]
val shared = mutableListOf("x")
collect("c", shared) // the default is not evaluated at all → [x, c]
shared // ⚠️ mutated: [x, c]
⚠️ The third call shows the other half of the picture: a collection passed explicitly is not copied. The function appends straight into the caller's list, so afterwards shared is [x, c] too.
If the default were evaluated once at load time (as in Python), the output would be [a], [a, b] — the most common wrong answer here.