💡 Инструкция: Выберите один ответ из пяти. На 20 вопросов отведено 55 минут. В каждом задании верен только один вариант. После завершения будут показаны общий результат и 4 тематических шкал.
Вопрос 7 из 20
Что стоит исправить в «Общее состояние замыканий» перед слиянием?
Kotlin Захват значений · Общее состояние замыканий Копировать
// Сохраните назначение фрагмента, но укрепите его контракт.
fun counters(): List<() -> Int> {
var n = 0
return List(3) { { ++n } }
}
fun main() = println(counters().map { it() })
Ограничиться поясняющим комментарием о том, что будет выведен `[3, 3, 3]`, так как инкремент выполняется при создании списка.
Сохранить API и считать достаточным условие: Будет выведен `[1, 1, 1]`, потому что каждая лямбда получает копию n.
Перенести проверку в вызывающий код, исходя из того, что возникнет `ConcurrentModificationException` при последовательных вызовах.
Спрятать участок за вспомогательной функцией, сохранив предположение: Код не компилируется: лямбда не может менять захваченную `var`.
Сделать состояние явным объектом или создать отдельную локальную переменную на итерацию, если счётчики должны быть независимыми.
Вопрос 10 из 20
На каком входе или состоянии граница «Общее состояние замыканий» становится заметной?
Проверить, сохраняется ли контракт, когда возникнет `ConcurrentModificationException` при последовательных вызовах.
Параллельные вызовы лямбд с общим `var` создают гонку: захват не добавляет атомарности или синхронизации.
Зафиксировать сценарий, где ожидается: Код не компилируется: лямбда не может менять захваченную `var`.
Добавить регрессию на гипотезу: Будет выведен `[1, 1, 1]`, потому что каждая лямбда получает копию n.
Проверить крайний ввод, при котором будет выведен `[3, 3, 3]`, так как инкремент выполняется при создании списка.
Вопрос 13 из 20
Решение для «Общее состояние замыканий»: Сделать состояние явным объектом или создать отдельную локальную переменную на итерацию, если счётчики должны быть независимыми. Что в нём остаётся не бесплатным?
Сопровождение усложнится, если окажется, что код не компилируется: лямбда не может менять захваченную `var`.
Замыкание удобно для небольшого состояния, но скрытое совместное владение ухудшает тестируемость и конкурентную безопасность.
После правки останется ограничение: Возникнет `ConcurrentModificationException` при последовательных вызовах.
Решение оправдано лишь при условии: Будет выведен `[1, 1, 1]`, потому что каждая лямбда получает копию n.
Обратная сторона изменения состоит в том, что будет выведен `[3, 3, 3]`, так как инкремент выполняется при создании списка.
Вопрос 15 из 20
Что изменить в «Лямбда после круглых скобок», чтобы скрытое допущение стало явным контрактом?
Kotlin Завершающая лямбда · Лямбда после круглых скобок Копировать
// Сохраните назначение фрагмента, но укрепите его контракт.
fun collect(prefix: String, block: (Int) -> String): String =
(1..3).joinToString(prefix = prefix, transform = block)
fun main() = println(collect("[") { n -> "$n]" })
Перенести проверку в вызывающий код, исходя из того, что будет напечатано `[1][2][3]`, потому что prefix применяется к каждому элементу.
Вынести участок в отдельный метод, считая верным следующее: Код не компилируется: trailing lambda разрешена только без других аргументов.
Оставить структуру прежней, документировав утверждение: Будет напечатано `1], 2], 3]`, поскольку prefix теряется после вынесения лямбды.
Использовать trailing lambda, когда она представляет исходное действие вызова; параметры конфигурации оставлять явно названными.
Обернуть операцию проверкой и не менять основной контракт: Возникнет ошибка из-за отсутствующего separator.
Вопрос 17 из 20
Как укрепить «Функция как значение», не переписывая соседние модули?
Kotlin Функциональные типы · Функция как значение Копировать
// Сохраните назначение фрагмента, но укрепите его контракт.
fun applyTwice(x: Int, f: (Int) -> Int) = f(f(x))
fun main() = println(applyTwice(3) { it + 2 })
Оставить структуру прежней, документировав утверждение: Возникнет ошибка, так как функцию нельзя вызвать больше одного раза.
Оставить реализацию без изменений и закрепить тестом предположение: Код не компилируется без явного типа параметра `it`.
Добавить защитную проверку перед фрагментом, поскольку будет выведено `5`, потому что результат первого вызова не передаётся во второй.
Перенести проверку в вызывающий код, исходя из того, что будет выведено `12`, поскольку лямбда умножается на число вызовов.
Называть функциональный параметр по роли и при сложном контракте заменить голую сигнатуру на `fun interface`.