web-dev-qa-db-fra.com

Les opérateurs "++" et "-" sont obsolètes. Xcode 7.3

Je regarde les notes Xcode 7.3 et je remarque ce problème.

Les opérateurs ++ et - sont obsolètes

Quelqu'un pourrait-il expliquer pourquoi il est déconseillé? Et ai-je raison de penser que dans la nouvelle version de Xcode, vous allez maintenant utiliser à la place de ++ this x += 1;

Exemple:

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

Screenshot for warning

135
Oleg Gordiichuk

A explication complète ici de Chris Lattner, créateur de Swift. Je vais résumer les points:

  1. C'est une autre fonction à apprendre lors de l'apprentissage de Swift
  2. Pas beaucoup plus court que x += 1
  3. Swift is not C. Ne les emportez pas uniquement pour faire plaisir aux programmeurs C
  4. Son utilisation principale est dans le style C pour la boucle: for i = 0; i < n; i++ { ... }, qui Swift a de meilleures alternatives, comme for i in 0..<n { ... } (le style C pour la boucle est sortant aussi )
  5. Cela peut être difficile à lire et à maintenir, par exemple, quelle est la valeur de x - ++x ou foo(++x, x++)?
  6. Chris Lattner n'aime pas ça.

Pour ceux qui sont intéressés (et pour éviter le lien de pourriture), les raisons de Lattner dans ses propres mots sont les suivantes:

  1. Ces opérateurs alourdissent le fardeau d'apprendre Swift en tant que premier langage de programmation - ou dans tout autre cas où vous ne connaissez pas déjà ces opérateurs dans un autre langage.

  2. Leur avantage expressif est minimal - x ++ n’est pas beaucoup plus court que x + = 1.

  3. Swift s'écarte déjà de C en ce que les opérations =, + = et autres opérations analogues à une affectation renvoient Void (pour un certain nombre de raisons). Ces opérateurs sont incompatibles avec ce modèle.

  4. Swift possède des fonctionnalités puissantes qui éliminent bon nombre des raisons courantes pour lesquelles vous utilisiez ++ i dans une boucle de style C dans d'autres langages. Elles sont donc relativement peu utilisées dans du code Swift bien écrit. Ces fonctionnalités incluent la boucle for-in, les plages, les énumérations, les cartes, etc.

  5. Le code qui utilise réellement la valeur de résultat de ces opérateurs est souvent source de confusion et de subtilité pour un lecteur/responsable de code. Ils encouragent le code "trop ​​compliqué" qui peut être mignon, mais difficile à comprendre.

  6. Bien que Swift ait un ordre d’évaluation bien défini, tout code qui en dépend (comme foo (++ a, a ++)) serait indésirable, même s’il était bien défini.

  7. Ces opérateurs sont applicables à relativement peu de types: les scalaires à nombres entiers et à virgule flottante et les concepts de type itérateur. Ils ne s'appliquent pas aux nombres complexes, matrices, etc.

Enfin, ceux-ci échouent à la métrique de "si nous ne les avions pas déjà, les ajouterions-nous à Swift 3?"

204
Code Different

Je réalise que ce commentaire ne répond pas à la question, mais il se peut que des personnes recherchent une solution pour que ces opérateurs restent actifs et une solution de ce type peut être trouvée dans la partie inférieure. ????

Personnellement, je préfère les opérateurs ++ et --. Je ne peux pas être d'accord avec l'opinion qu'ils sont difficiles ou difficiles à gérer. Une fois que le développeur a compris ce que font ces opérateurs (et nous parlons de choses assez simples), le code doit être très clair.

Dans l'explication de la désapprobation des opérateurs, il est mentionné que leur utilisation principale était dans le style C pour les boucles. Je ne connais pas les autres, mais personnellement, je n'utilise pas du tout de boucles de style C et il existe encore de nombreux autres endroits ou situations où l'opérateur ++ ou -- est utile.

Je voudrais également mentionner que varName++ renvoie une valeur afin qu'elle puisse être utilisée dans la return alors que varName += 1 ne le peut pas.

Pour ceux d'entre vous qui souhaitent que ces opérateurs restent actifs, voici la solution:

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
}
36
0101

Apple a supprimé le ++ et l'a rendu beaucoup plus simple avec un autre moyen traditionnel.

Au lieu de ++, vous devez écrire +=.

Exemple:

var x = 1

//Increment
x += 1 //Means x = x + 1 

De même pour l'opérateur de décrémentation --, vous devez écrire -=

Exemple:

var x = 1

//Decrement
x -= 1 //Means x = x - 1

Pour les boucles for:

Exemple d'incrémentation:

Au lieu de

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

Vous pouvez écrire:

//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)")
}

Exemple de décrémentation:

for var index = 3; index >= 0; --index {
   print(index)
}

Vous pouvez écrire:

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)
}

J'espère que cela t'aides!

22
Sohil R. Memon

Chris Lattner est parti en guerre contre ++ et -. Il écrit: "Un code qui utilise réellement la valeur de résultat de ces opérateurs est souvent source de confusion et de subtilité pour un lecteur/responsable de code. Ils encouragent le code "trop compliqué" qui peut être mignon, mais difficile à comprendre…. Alors que Swift a un ordre d'évaluation bien défini, tout code qui en dépend (comme foo (++ a, a ++)) serait indésirable même s'il était bien défini… ceux-ci échouent à la métrique de "si nous ne les avions pas déjà, les ajouterions-nous à Swift 3?

Apple souhaitait conserver Swift un langage propre, clair, ne prêtant pas à confusion et directement au point. Et ils ont donc déconseillé d'utiliser ++ et - keyword.

8
Jay Mehta

Screenshot for warning

Le _Fix-it feature_ de Xcode donne une réponse claire à cela.

Solution to warning

Remplacez _++ increment operator_ par _value += 1_ (opérateur à main courte) et _-- decrement operator_ par _value -= 1_

6
Jayprakash Dubey

Pour Swift 4, vous pouvez restaurer les opérateurs ++ et -- en tant qu'extensions pour Int et d'autres types. Voici un exemple:

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
    }
}

Cela fonctionne de la même manière pour d'autres types, tels que UIInt, Int8, Float, Double, etc.

Vous pouvez coller ces extensions dans un seul fichier de votre répertoire racine. Elles pourront être utilisées dans tous vos autres fichiers.

J'ai remarqué quelques votes négatifs pour ma réponse ici, presque aussitôt que je l'ai postée. Ce que je considère comme un désaccord philosophique plutôt que comme une critique du fonctionnement de mon code. Cela fonctionne parfaitement, si vous vérifiez dans une aire de jeux.

J'ai posté cette réponse parce que je ne suis pas d'accord avec l'idée de rendre les langages de programmation informatique inutilement différents les uns des autres.

Avoir beaucoup de similitudes entre les langues les rend plus faciles à apprendre et à passer d’une langue à l’autre.

Les développeurs utilisent normalement plusieurs langages de programmation plutôt qu'un seul. Et passer d'une langue à une autre est une vraie galère, quand il n'y a pas de conventions et pas de standardisation commune à toutes les langues.

Je crois qu'il devrait y avoir des différences de syntaxe entre les langues seulement autant que nécessaire, et pas plus que cela.

4
Mike

De la docs :

Les opérateurs d’incrémentation/décrémentation dans Swift ont été ajoutés très tôt dans le développement de Swift, en tant que report de C. Ils ont été ajoutés sans trop de considération et n’avaient plus été considérés depuis. Ce document fournit un regard neuf sur eux, et recommande en fin de compte de simplement les supprimer entièrement, car ils sont source de confusion et ne portent pas leur poids.

4
Dániel Nagy

Voici une version générique de certains des codes postés jusqu'à présent. Je voudrais exprimer les mêmes préoccupations que d’autres: c’est une bonne pratique de pas les utiliser dans Swift. Je conviens que cela pourrait être déroutant pour ceux qui liront votre code à l'avenir.

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
}

Cela peut également être écrit comme une extension sur le type numérique.

3
Doghound
var value : Int = 1

func theOldElegantWay() -> Int{
return value++
}

func theNewFashionWay() -> Int{
let temp = value
value += 1
return temp
}

C'est définitivement un inconvénient, non?

0
outcast