Операторы "++" и "-" устарели в Xcode 7.3
Я смотрю на заметки Xcode 7.3 и замечаю эту проблему.
Операторы ++ и - устарели
Может ли кто-нибудь объяснить, почему это устарело? И я прав, что в новой версии XCode теперь вы собираетесь использовать вместо ++
этот x += 1
;
Пример:
for var index = 0; index < 3; index += 1 {
print("index is \(index)")
}
14 ответов
Полное объяснение здесь от Криса Латтнера, создателя Swift. Я подведу итоги:
- Это еще одна функция, которую вы должны изучить, изучая Swift
- Не намного короче
x += 1
- Swift - это не C. Не стоит переносить их, чтобы угодить программистам на C
- Его основное использование в стиле C для цикла:
for i = 0; i < n; i++ { ... }
, который Swift имеет лучшие альтернативы, какfor i in 0..<n { ... }
(C-стиль для цикла также выходит) - Может быть сложно читать и поддерживать, например, какова ценность
x - ++x
или жеfoo(++x, x++)
? - Крису Латтнеру это не нравится.
Для тех, кто заинтересован (и чтобы избежать гниения ссылок), причины Латтнера в его собственных словах:
Эти операторы увеличивают бремя изучения Swift как первого языка программирования - или любого другого случая, когда вы еще не знаете этих операторов с другого языка.
Их выразительное преимущество минимально - х ++ не намного короче х + = 1.
Swift уже отклоняется от C в том смысле, что =, += и другие подобные операции возвращают Void (по ряду причин). Эти операторы несовместимы с этой моделью.
Swift обладает мощными функциями, которые устраняют многие из распространенных причин, по которым вы используете ++ i в цикле for в стиле C на других языках, поэтому они относительно редко используются в хорошо написанном коде Swift. Эти функции включают цикл for-in, диапазоны, перечисление, отображение и т. Д.
Код, который фактически использует значение результата этих операторов, часто вводит в заблуждение и тонок для читателя / сопровождающего кода. Они поощряют "чрезмерно хитрый" код, который может быть симпатичным, но трудным для понимания.
Хотя Swift имеет четко определенный порядок оценки, любой код, который зависит от него (например, foo(++a, a++)), будет нежелательным, даже если он будет четко определен.
Эти операторы применимы к относительно небольшому числу типов: целочисленные скаляры и скаляры с плавающей точкой, а также итератороподобные концепции. Они не применяются к комплексным числам, матрицам и т. Д.
Наконец, они не соответствуют метрике "если бы у нас их еще не было, мы бы добавили их в Swift 3?"
Я понимаю, что этот комментарий не отвечает на вопрос, тем не менее, могут быть люди, которые ищут решение, как сохранить работу этих операторов, и такое решение можно найти внизу.
Я лично предпочитаю ++
а также --
операторы. Я не могу согласиться с мнением, что они сложны или сложны в управлении. Как только разработчик поймет, что делают эти операторы (а мы говорим о довольно простых вещах), код должен стать очень понятным.
В объяснении, почему операторы устарели, упоминается, что их основное использование было в C-стиле для циклов. Я не знаю о других, но лично я вообще не использую петли в стиле C, и есть еще много других мест или ситуаций, когда ++
или же --
Оператор полезен.
Я хотел бы также отметить, что 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
}
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)
}
Надеюсь это поможет!
Для 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 имеет четко определенный порядок вычисления, любой код, который зависит от него (например, foo(++a, a++)), будет нежелательным, даже если он был четко определен… они не соответствуют метрике "если бы у нас их еще не было, мы бы добавили их в Swift 3?" "
Apple хотела сохранить быстрый, понятный, понятный и понятный язык. И поэтому они устарели ++ и - ключевое слово.
Fix-it feature
Xcode дает четкий ответ на это.
замещать ++ increment operator
со старомодным value += 1
(оператор короткой руки) и -- decrement operator
с value -= 1
Вот общая версия некоторого кода, опубликованного до сих пор. Я бы высказал те же опасения, что и другие: лучше не использовать их в 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
}
Это также можно записать как расширение типа Numeric.
Из документов:
Операторы инкремента / декремента в Swift были добавлены очень рано при разработке Swift, как переход от C. Они были добавлены без особого рассмотрения, и с тех пор о них много не думали. Этот документ дает свежий взгляд на них и в конечном итоге рекомендует просто полностью удалить их, поскольку они сбивают с толку и не несут своего веса.
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
}
На языке без точки с запятой это может быть неоднозначным. Это префиксный или постфиксный оператор?
Рассмотреть возможность:
var x = y
++x
Человек читает
++x
но парсер мог прочитать это как
y++
.
Это изменение не кажется таким уж плохим. ++i и i++ могут легко "перечитываться" и не распознавать отключение по одной ошибке, особенно для начинающих программистов, которым еще только нужно вырвать глаза и потерять подругу, чтобы отладить ее один или два раза. Тем не менее, изменение основных аспектов языка - это действительно проблема, которая остановит и, возможно, предотвратит его широкое использование.
// This appears to work, so you don't need a temp var,
// you do need to pass something in or have it be a
// method on the struct or class.
// I probably wouldn't actually write a function
// just to increment a given value.
// I'd just increment it where I needed too.
// Otherwise, you copy a value and return it.
func otherNewIncrement(newValue : Int) -> Int {
return newValue + 1
}
В 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++ и многое другое. Программисты с удовольствием этим пользуются. Кому бы ни было сложно понять этот оператор, они и только они должны делать += (или, возможно, s = s + 1, если += также слишком сложен).
Стратегия Swift проста: Apple считает, что программист глуп, и поэтому к нему следует относиться соответствующим образом.
Правда в том, что Swift, запущенный в сентябре 2014 года, должен был быть где-то еще. Другие языки росли намного быстрее.
Я могу перечислить много основных ошибок в языке, от серьезных: таких как массивы, вставленные по значению, а не по ссылке, до надоедливых: функции с переменными параметрами не могут принять массив, который является основной идеей. Я не думаю, что сотрудникам Apple даже разрешают смотреть на другие языки, такие как Java, поэтому они даже не знают, что Apple отстает от света. Apple могла бы принять Java как язык, но в наши дни проблема не в технологии, а в эго. Если бы они открыли IntelliJ для написания Java, они наверняка закрыли бы свой бизнес, понимая, что на данный момент они не могут и не догонят никогда.
i += 1
возвращается Void
, что является наиболее важным моментом. Так, ++i
а также i++
вернуть Void
, тоже. Они сохранят то же значение. В это время вы поймете, что удалить его лучше, как это делает Python.