Что выведет функция, у которой аргумент по умолчанию создаёт новый список?
Функция ниже принимает список со значением по умолчанию и добавляет в него один элемент. Её вызывают трижды: дважды без второго аргумента и один раз со списком, которым владеет вызывающая сторона.
Ограничения: рассуждайте только по правилам языка — без рефлексии и трюков библиотеки. Укажите точно, что печатает каждый из трёх вызовов println, и обоснуйте каждую строку.
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))
}
Определите вывод и объясните почему.
Печатается [a], затем [b], затем [x, c]. Значение по умолчанию — выражение, вычисляемое заново при каждом вызове с опущенным аргументом, поэтому каждый такой вызов строит свой список. Явная передача shared дописывает в этот список.
- ✗Переносить привычку Python, где умолчание вычисляется один раз при определении
- ✗Считать, что явно переданный аргумент копируется, а не разделяется
- ✗Думать, что умолчание обязано быть константой, а не любым выражением
- →Может ли умолчание ссылаться на более ранний параметр той же функции?
- →Что происходит с умолчаниями, когда функцию вызывают из Java?
Вывод
[a]
[b]
[x, c]
Почему
Значение по умолчанию в Kotlin — это выражение, а не константа, и оно вычисляется заново при каждом вызове, где аргумент опущен. Никакого «одного списка на всю функцию» не существует.
fun collect(item: String, into: MutableList<String> = mutableListOf()): MutableList<String> {
into.add(item)
return into
}
collect("a") // into = новый список → [a]
collect("b") // into = ещё один новый список → [b]
val shared = mutableListOf("x")
collect("c", shared) // умолчание не вычисляется вовсе → [x, c]
shared // ⚠️ мутирован: [x, c]
⚠️ Третий вызов показывает вторую половину картины: явно переданная коллекция не копируется. Функция дописывает прямо в список вызывающей стороны, поэтому после вызова shared тоже равен [x, c].
Если бы умолчание вычислялось один раз при загрузке (как в Python), вывод был бы [a], [a, b] — это самая частая ошибка на таком вопросе.