Операторы "++" и "-" устарели в Xcode 7.3

Я смотрю на заметки Xcode 7.3 и замечаю эту проблему.

Операторы ++ и - устарели

Может ли кто-нибудь объяснить, почему это устарело? И я прав, что в новой версии XCode теперь вы собираетесь использовать вместо ++ этот x += 1;

Пример:

for var index = 0; index < 3; index += 1 {
    print("index is \(index)")
}

Снимок экрана для предупреждения

14 ответов

Решение

Полное объяснение здесь от Криса Латтнера, создателя Swift. Я подведу итоги:

  1. Это еще одна функция, которую вы должны изучить, изучая Swift
  2. Не намного короче x += 1
  3. Swift - это не C. Не стоит переносить их, чтобы угодить программистам на C
  4. Его основное использование в стиле C для цикла: for i = 0; i < n; i++ { ... }, который Swift имеет лучшие альтернативы, как for i in 0..<n { ... } (C-стиль для цикла также выходит)
  5. Может быть сложно читать и поддерживать, например, какова ценность x - ++x или же foo(++x, x++)?
  6. Крису Латтнеру это не нравится.

Для тех, кто заинтересован (и чтобы избежать гниения ссылок), причины Латтнера в его собственных словах:

  1. Эти операторы увеличивают бремя изучения Swift как первого языка программирования - или любого другого случая, когда вы еще не знаете этих операторов с другого языка.

  2. Их выразительное преимущество минимально - х ++ не намного короче х + = 1.

  3. Swift уже отклоняется от C в том смысле, что =, += и другие подобные операции возвращают Void (по ряду причин). Эти операторы несовместимы с этой моделью.

  4. Swift обладает мощными функциями, которые устраняют многие из распространенных причин, по которым вы используете ++ i в цикле for в стиле C на других языках, поэтому они относительно редко используются в хорошо написанном коде Swift. Эти функции включают цикл for-in, диапазоны, перечисление, отображение и т. Д.

  5. Код, который фактически использует значение результата этих операторов, часто вводит в заблуждение и тонок для читателя / сопровождающего кода. Они поощряют "чрезмерно хитрый" код, который может быть симпатичным, но трудным для понимания.

  6. Хотя Swift имеет четко определенный порядок оценки, любой код, который зависит от него (например, foo(++a, a++)), будет нежелательным, даже если он будет четко определен.

  7. Эти операторы применимы к относительно небольшому числу типов: целочисленные скаляры и скаляры с плавающей точкой, а также итератороподобные концепции. Они не применяются к комплексным числам, матрицам и т. Д.

Наконец, они не соответствуют метрике "если бы у нас их еще не было, мы бы добавили их в 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.

Другие вопросы по тегам