Я написал расширение для Array
, которое позволяет мне вытолкнуть последний элемент и мгновенно добавить его в другой массив:
extension Array {
mutating func popLast(to otherArray: inout [Element]) -> Element? {
guard self.count > 0 else { return nil }
return otherArray.appendAndReturn(self.popLast()!)
}
mutating func appendAndReturn(_ element: Element) -> Element {
self.append(element)
return element
}
}
Этот простой пример на детской площадке работает как шарм:
var newNumbers = [1,2,3,4,5,6,7,8,9]
var usedNumbers: [Int] = []
newNumbers.popLast(to: &usedNumbers)
print(usedNumbers) // [9]
for _ in newNumbers {
newNumbers.popLast(to: &usedNumbers)
}
print(usedNumbers) // [9, 8, 7, 6, 5, 4, 3, 2, 1]
Но использование расширения внутри структуры (код после предупреждения) дает мне такое предупреждение:
Одновременный доступ к параметру self, но для изменения требуется монопольный доступ; рассмотрите возможность копирования в локальную переменную
struct Test {
var newNumbers = [1,2,3,4,5,6,7,8,9]
var usedNumbers: [Int] = []
mutating func getNewNumber() -> Int? {
return newNumbers.popLast(to: &usedNumbers)
}
}
Это всего лишь предупреждение, и мое приложение отлично работает с ожидаемым поведением, но мне любопытно, действительно ли здесь существует опасность. Глядя на заголовок SE-0176, я понимаю цель предупреждения, если бы я использовал его для извлечения последнего элемента из того же массива, в который я его добавляю, потому что копирование при записи может испортить это. Думаю, это связано со структурой. Но, используя его на двух разных массивах внутри одной структуры, я не вижу опасности. Я что-то упустил, и есть ли способ написать расширение, которое обойдет потенциальную проблему?
newNumbers
иusedNumbers
переменными-членами структуры? Это объяснило бы упоминание о доступе кself
. - person David Rönnqvist   schedule 27.06.2017struct
здесь. - person Benno Kress   schedule 27.06.2017mutating
. И Доступ к различным сохраненным свойствам структуры или различным элементам кортежа может перекрываться, поэтому одновременный доступ на запись дляnewNumbers
&usedNumbers
не должен быть проблемой. - person Hamish   schedule 27.06.2017modifying(&object.pair) { pair in swap(&pair.x, &pair.y) }
фактически не компилируется, потому что компилятор считает, что одновременный доступ на запись кpair.x
иpair.y
в конфликтах закрытия. - person Hamish   schedule 27.06.2017