Я просматриваю заметки Xcode 7.3 и замечаю эту проблему.
Операторы ++ и - устарели
Может ли кто-нибудь объяснить, почему он устарел? И я прав, что в новой версии Xcode теперь вы собираетесь использовать вместо ++
этого x += 1
;
Пример:
for var index = 0; index < 3; index += 1 {
print("index is \(index)")
}
++
и--
операторовОтветы:
Полное объяснение здесь от Криса Lattner, создателя Свифта. Подытожу по пунктам:
x += 1
for i = 0; i < n; i++ { ... }
которого Swift есть лучшие альтернативы, напримерfor i in 0..<n { ... }
(цикл for в стиле C также выходит )x - ++x
илиfoo(++x, x++)
?Для тех, кто заинтересован (и во избежание гниения ссылок), Латтнер своими словами приводит следующие доводы:
источник
++
бы в языках C-стиля не существовало, никто в здравом уме не взглянул бы на дизайн Swift 3.0 и не подумал бы, что++
оператор был бы хорошим дополнением к нему.Я понимаю, что этот комментарий не отвечает на вопрос, тем не менее, могут быть люди, которые ищут решение, как сохранить эти операторы в рабочем состоянии, и такое решение можно найти внизу. 😇
Я лично предпочитаю
++
и--
операторов. Не могу согласиться с мнением, что ими сложно или сложно управлять. Как только разработчик поймет, что делают эти операторы (а мы говорим о довольно простых вещах), код должен быть очень ясным.В объяснении, почему операторы объявлены устаревшими, упоминается, что их основное использование было в C-стиле для циклов. Я не знаю, как другие, но я лично не использую циклы в стиле C, и есть еще много других мест или ситуаций, когда полезен оператор
++
or--
.Я хотел бы также отметить , что
varName++
возвращает значение , поэтому он может быть использован вreturn
то время какvarName += 1
не может.Для любого из вас, кто хотел бы, чтобы эти операторы работали, вот решение:
prefix operator ++ {} postfix operator ++ {} prefix operator -- {} postfix operator -- {} // Increment prefix func ++(inout x: Int) -> Int { x += 1 return x } postfix func ++(inout x: Int) -> Int { x += 1 return (x - 1) } prefix func ++(inout x: UInt) -> UInt { x += 1 return x } postfix func ++(inout x: UInt) -> UInt { x += 1 return (x - 1) } prefix func ++(inout x: Int8) -> Int8 { x += 1 return x } postfix func ++(inout x: Int8) -> Int8 { x += 1 return (x - 1) } prefix func ++(inout x: UInt8) -> UInt8 { x += 1 return x } postfix func ++(inout x: UInt8) -> UInt8 { x += 1 return (x - 1) } prefix func ++(inout x: Int16) -> Int16 { x += 1 return x } postfix func ++(inout x: Int16) -> Int16 { x += 1 return (x - 1) } prefix func ++(inout x: UInt16) -> UInt16 { x += 1 return x } postfix func ++(inout x: UInt16) -> UInt16 { x += 1 return (x - 1) } prefix func ++(inout x: Int32) -> Int32 { x += 1 return x } postfix func ++(inout x: Int32) -> Int32 { x += 1 return (x - 1) } prefix func ++(inout x: UInt32) -> UInt32 { x += 1 return x } postfix func ++(inout x: UInt32) -> UInt32 { x += 1 return (x - 1) } prefix func ++(inout x: Int64) -> Int64 { x += 1 return x } postfix func ++(inout x: Int64) -> Int64 { x += 1 return (x - 1) } prefix func ++(inout x: UInt64) -> UInt64 { x += 1 return x } postfix func ++(inout x: UInt64) -> UInt64 { x += 1 return (x - 1) } prefix func ++(inout x: Double) -> Double { x += 1 return x } postfix func ++(inout x: Double) -> Double { x += 1 return (x - 1) } prefix func ++(inout x: Float) -> Float { x += 1 return x } postfix func ++(inout x: Float) -> Float { x += 1 return (x - 1) } prefix func ++(inout x: Float80) -> Float80 { x += 1 return x } postfix func ++(inout x: Float80) -> Float80 { x += 1 return (x - 1) } prefix func ++<T : _Incrementable>(inout i: T) -> T { i = i.successor() return i } postfix func ++<T : _Incrementable>(inout i: T) -> T { let y = i i = i.successor() return y } // Decrement prefix func --(inout x: Int) -> Int { x -= 1 return x } postfix func --(inout x: Int) -> Int { x -= 1 return (x + 1) } prefix func --(inout x: UInt) -> UInt { x -= 1 return x } postfix func --(inout x: UInt) -> UInt { x -= 1 return (x + 1) } prefix func --(inout x: Int8) -> Int8 { x -= 1 return x } postfix func --(inout x: Int8) -> Int8 { x -= 1 return (x + 1) } prefix func --(inout x: UInt8) -> UInt8 { x -= 1 return x } postfix func --(inout x: UInt8) -> UInt8 { x -= 1 return (x + 1) } prefix func --(inout x: Int16) -> Int16 { x -= 1 return x } postfix func --(inout x: Int16) -> Int16 { x -= 1 return (x + 1) } prefix func --(inout x: UInt16) -> UInt16 { x -= 1 return x } postfix func --(inout x: UInt16) -> UInt16 { x -= 1 return (x + 1) } prefix func --(inout x: Int32) -> Int32 { x -= 1 return x } postfix func --(inout x: Int32) -> Int32 { x -= 1 return (x + 1) } prefix func --(inout x: UInt32) -> UInt32 { x -= 1 return x } postfix func --(inout x: UInt32) -> UInt32 { x -= 1 return (x + 1) } prefix func --(inout x: Int64) -> Int64 { x -= 1 return x } postfix func --(inout x: Int64) -> Int64 { x -= 1 return (x + 1) } prefix func --(inout x: UInt64) -> UInt64 { x -= 1 return x } postfix func --(inout x: UInt64) -> UInt64 { x -= 1 return (x + 1) } prefix func --(inout x: Double) -> Double { x -= 1 return x } postfix func --(inout x: Double) -> Double { x -= 1 return (x + 1) } prefix func --(inout x: Float) -> Float { x -= 1 return x } postfix func --(inout x: Float) -> Float { x -= 1 return (x + 1) } prefix func --(inout x: Float80) -> Float80 { x -= 1 return x } postfix func --(inout x: Float80) -> Float80 { x -= 1 return (x + 1) } prefix func --<T : BidirectionalIndexType>(inout i: T) -> T { i = i.predecessor() return i } postfix func --<T : BidirectionalIndexType>(inout i: T) -> T { let y = i i = i.predecessor() return y }
источник
return (x - 1)
операторы постфикса - ИМХО, лучше поддерживать семантику, которую они возвращают (копию) исходного значения, а не то, что вы получите, если это сделаетеx + 1 - 1
Int
только о том, что результат(x + 1)
будет переполнен, что прервет выполнение и, следовательноresult - 1
, даже не будет запущено. Однако другие типы данных, такие как,Double
например, ведут себя по-другому, поэтому мне нужно это исследовать.defer
для этого.defer { x += 1 }; return x
Apple удалила
++
и упростила это другим старым традиционным способом.Вместо этого
++
вам нужно написать+=
.Пример:
var x = 1 //Increment x += 1 //Means x = x + 1
Аналогично для оператора декремента
--
нужно написать-=
Пример:
var x = 1 //Decrement x -= 1 //Means x = x - 1
Для
for
петель:Пример приращения:
Вместо того
for var index = 0; index < 3; index ++ { print("index is \(index)") }
Ты можешь написать:
//Example 1 for index in 0..<3 { print("index is \(index)") } //Example 2 for index in 0..<someArray.count { print("index is \(index)") } //Example 3 for index in 0...(someArray.count - 1) { print("index is \(index)") }
Пример уменьшения:
for var index = 3; index >= 0; --index { print(index) }
Ты можешь написать:
for index in 3.stride(to: 1, by: -1) { print(index) } //prints 3, 2 for index in 3.stride(through: 1, by: -1) { print(index) } //prints 3, 2, 1 for index in (0 ..< 3).reverse() { print(index) } for index in (0 ... 3).reverse() { print(index) }
Надеюсь это поможет!
источник
+=
был там все время.++i
и--i
?Крис Латтнер начал войну против ++ и -. Он пишет: «Код, который фактически использует значение результата этих операторов, часто сбивает с толку и неуловим для читателя / разработчика кода. Они поощряют «чрезмерно хитрый» код, который может показаться симпатичным, но трудным для понимания… .Хотя Swift имеет четко определенный порядок оценки, любой код, который зависит от него (например, foo (++ a, a ++)), был бы нежелательным, даже если бы он был четко определен ... они не соответствуют метрике «если бы у нас их еще не было, добавили бы мы их в Swift 3?» »
Apple хотела сохранить чистый, ясный, понятный, понятный и понятный язык. И поэтому они устарели ключевыми словами ++ и -.
источник
...for i in 0.stride(to: 10, by: 2)...
или...for i in (1...10).reverse()...
чисто ?!Fix-it feature
Из Xcode дает четкий ответ на этот вопрос.Заменить
++ increment operator
на старомодныйvalue += 1
(сокращенный оператор) и-- decrement operator
наvalue -= 1
источник
Для Swift 4, вы можете восстановить
++
и--
оператор в качестве расширений дляInt
и других типов. Вот пример:extension Int{ static prefix func ++(x: inout Int) -> Int { x += 1 return x } static postfix func ++(x: inout Int) -> Int { defer {x += 1} return x } static prefix func --(x: inout Int) -> Int { x -= 1 return x } static postfix func --(x: inout Int) -> Int { defer {x -= 1} return x } }
Он работает так же , как и для других типов, таких как
UIInt
,Int8
,Float
,Double
и т.д.Вы можете вставить эти расширения в один файл в корневой каталог, и они будут доступны для использования во всех других ваших файлах.
Я заметил несколько голосов против моего ответа здесь, почти сразу после того, как опубликовал его. Я воспринимаю это скорее как философское несогласие, чем критику того, как работает мой код. Он отлично работает, если посмотреть на детской площадке.
Причина, по которой я опубликовал этот ответ, заключается в том, что я не согласен с тем, чтобы языки компьютерного программирования излишне отличались друг от друга.
Наличие большого количества общего между языками облегчает их изучение и переключение с одного языка на другой.
Разработчики обычно используют несколько языков программирования, а не один. А переключаться с одного языка на другой, когда нет соглашений и нет общей стандартизации для разных языков, - это настоящая проблема.
Я считаю, что синтаксических различий между языками должно быть ровно столько, сколько необходимо, и не более того.
источник
Вот общая версия кода, опубликованного на данный момент. Я хотел бы выразить те же опасения, что и другие: лучше не использовать их в Swift. Я согласен, что это может сбить с толку тех, кто читает ваш код в будущем.
prefix operator ++ prefix operator -- prefix func ++<T: Numeric> (_ val: inout T) -> T { val += 1 return val } prefix func --<T: Numeric> (_ val: inout T) -> T { val -= 1 return val } postfix operator ++ postfix operator -- postfix func ++<T: Numeric> (_ val: inout T) -> T { defer { val += 1 } return val } postfix func --<T: Numeric> (_ val: inout T) -> T { defer { val -= 1 } return val }
Это также можно записать как расширение числового типа.
источник
@discardableResult
к каждой из этих функций, чтобы отключить предупреждение о неиспользовании возвращаемого значения; в остальном именно то, что я искал.Из документов :
источник
var value : Int = 1 func theOldElegantWay() -> Int{ return value++ } func theNewFashionWay() -> Int{ let temp = value value += 1 return temp }
Это определенно недостаток, правда?
источник
Поскольку вы никогда не работаете с указателями в Swift, на мой взгляд, имеет смысл удалить операторы
++
и--
. Однако, если вы не можете жить без него, вы можете добавить в свой проект следующие объявления операторов Swift 5+ :@discardableResult public prefix func ++<T: Numeric>(i: inout T) -> T { i += 1 return i } @discardableResult public postfix func ++<T: Numeric>(i: inout T) -> T { defer { i += 1 } return i } @discardableResult public prefix func --<T: Numeric>(i: inout T) -> T { i -= 1 return i } @discardableResult public postfix func --<T: Numeric>(i: inout T) -> T { defer { i -= 1 } return i }
источник
В Swift 4.1 это можно было сделать так:
prefix operator ++ postfix operator ++ extension Int{ static prefix func ++(x: inout Int)->Int{ x += 1 return x } static postfix func ++(x: inout Int)->Int{ x += 1 return x-1 } } //example: var t = 5 var s = t++ print("\(t) \(s)")
Обратите внимание, что, несмотря на то, что это решение похоже на предыдущие решения в этом посте, они больше не работают в Swift 4.1, как и в этом примере. Также обратите внимание, что тот, кто выше упоминает, что + = является заменой для ++, просто не полностью понимает оператор, поскольку ++ в сочетании с присваиванием на самом деле представляет собой две операции, следовательно, ярлык. В моем примере:
var s = t++
выполняет две вещи: присваивает значение t переменной s и затем увеличивает t. Если до него идет ++, это те же две операции, выполняемые в обратном порядке. На мой взгляд, рассуждения Apple о том, почему нужно удалить этот оператор (упомянутые в предыдущих ответах), не только ложные рассуждения, но, более того, я считаю, что это ложь, и истинная причина в том, что они не могли заставить свой компилятор справиться с этим. В предыдущих версиях это доставляло им проблемы, поэтому они сдались. Логика «слишком сложный для понимания оператор, следовательно, удаленный» - очевидная ложь, потому что Swift содержит гораздо более сложные и гораздо менее полезные операторы, которые не были удалены. Кроме того, он есть в подавляющем большинстве языков программирования. JavaScript, C, C #, Java, C ++ и многие другие. Программисты с удовольствием этим пользуются. Кому бы ни было сложно понять этот оператор,Стратегия Swift проста: Apple считает, что программист тупой, и поэтому к нему следует относиться соответственно.
На самом деле Swift, запущенный в сентябре 2014 года, должен был быть где-то еще. Другие языки выросли намного быстрее.
Я могу перечислить множество серьезных ошибок в языке, от серьезных: например, массивы, вставленные по значению, а не по ссылке, до раздражающих: функции с переменными параметрами не могут принимать массив, что и является основной идеей. Я не думаю, что сотрудникам Apple разрешено даже смотреть на другие языки, такие как Java, поэтому они даже не знают, что Apple отстает на световые годы. Apple могла бы принять Java в качестве языка, но в наши дни проблема не в технологиях, а в эго. Если бы они открыли IntelliJ для написания Java, они бы наверняка закрыли свой бизнес, понимая, что на данный момент они не могут и никогда не догонят.
источник