Изменение массива вызывающего на месте через параметр inout
Напишите removeEvens(from:), который меняет массив вызывающего на месте — убирая все чётные числа — через параметр inout, не возвращая новый массив.
Ограничения:
- Изменяйте переданный массив напрямую; вызывающий видит изменение после вызова.
- Не выделяйте и не возвращайте отдельный массив.
func removeEvens(from numbers: inout [Int]) {
// ваш код здесь
}
Затем в одну строку объясните, почему параметр inout нельзя захватить в escaping-замыкании. Допишите реализацию.
inout использует copy-in/copy-out — вызываемая сторона меняет локальную копию, которая при возврате пишется обратно в переменную вызывающего; вызов через &list. Захватить его в escaping-замыкании нельзя: время жизни параметра кончается при возврате, и отложенная запись попала бы в мёртвую переменную.
- ✗Думают, что
inoutпередаёт по ссылке, как указатель C, а не copy-in/copy-out - ✗Забывают префикс
&на месте вызова - ✗Полагают, что параметр
inoutможно спрятать в escaping-замыкании на потом
- →Почему copy-out происходит при возврате, а не при каждой записи внутри функции?
- →Чем параметр
inoutотличается от передачи экземпляраclass?
Решение изменяет массив на месте, а & на месте вызова делает copy-in/copy-out явным:
func removeEvens(from numbers: inout [Int]) {
numbers.removeAll { $0 % 2 == 0 }
}
var list = [1, 2, 3, 4, 5, 6]
removeEvens(from: &list) // list == [1, 3, 5]
inout не передаёт по ссылке: аргумент копируется внутрь, функция меняет копию, а при возврате значение записывается обратно в list. Захватить inout-параметр в escaping-замыкании нельзя, потому что copy-out и время жизни параметра завершаются при возврате, — отложенная запись писала бы в переменную, которой уже нет.