web-dev-qa-db-fra.com

Comment créez-vous un tableau immuable dans Swift?

Comment créer un tableau immuable dans Swift?

Une lecture superficielle de la documentation suggérerait que vous pouvez simplement faire 

let myArray = [1,2,3]

Mais malheureusement, cela produit réellement un tableau modifiable de taille fixe. Cette mutabilité crée les énigmes habituelles avec un aliasing insoupçonné et des fonctions qui modifient leurs arguments:

let outterArray = [myArray, myArray]
outterArray[0][0] = 2000
outterArray //=> [[2000,2,3],[2000,2,3]]   surprise!

func notReallyPure(arr:Int[]) -> () { arr[0] = 3000 }
notReallyPure(myArray)
myArray // => [3000,2,3]

Pas beaucoup mieux que C.

Si je veux l'immuabilité, est la meilleure option pour l'envelopper dans une NSArray comme ceci:

let immutableArray = NSArray(myArray: [1,2,3])

Cela semble fou. Qu'est-ce que j'oublie ici?

MISE À JOUR (2015-07-26):

Cette question date des tout premiers jours de Swift. Swift a depuis été mis à jour pour que les tableaux immuables soient réellement immuables, comme l'indiquent les réponses ci-dessous.

30
algal

Cela a changé avec Xcode 6 bêta 3. Alors que les tableaux étaient semi-mutables, comme vous le décrivez, avec des éléments variables mais de longueur fixe, les tableaux maintenant immuables partagent la même sémantique que les dictionnaires:

Des notes de publication de Xcode 6 beta 3:

• Array dans Swift a été complètement repensé pour avoir une sémantique de valeur complète comme Dictionnaire et String l’ont toujours été dans Swift. Cela résout divers problèmes de mutabilité - maintenant un tableau 'let' est complètement immuable, et un tableau 'var' est complètement mutable - compose correctement avec Dictionary et String, et résout d'autres problèmes plus profonds. La sémantique des valeurs peut être surprenante si vous êtes habitué aux tableaux NSArray ou C: une copie du tableau produit maintenant une copie complète et indépendante de tous les éléments grâce à une implémentation efficace de la copie paresseuse. Il s’agit d’un changement majeur pour Array et il reste encore quelques problèmes de performances à résoudre. S'il vous plaît ! voyez le langage de programmation Swift pour plus d'informations. (17192555)

Les informations originales sur les tableaux dans Swift Book ont ​​été mises à jour le 7 juillet 2014 pour refléter les modifications apportées à la bêta 3. (Si vous utilisez iBooks sur un Mac, comme moi, vous devrez peut-être le supprimer et le télécharger à nouveau pour obtenir la mise à jour du 7 juillet — je ne pouvais pas obtenir la mise à jour automatique.)

27
Matt Gibson

Semble être un bug et être corrigé bientôt.

Cité de Apple dev forum :

Question:

Incohérence avec let for Array et Dictionary

Réponse finale:

Ceci est considéré comme un bug, pas une fonctionnalité, et sera corrigé dans un plus tard Beta.
-Chris

8
Eonil

C'est maintenant possible.

De Développeur Apple

Si vous affectez un tableau ou un dictionnaire à une constante, ce tableau ou dictionnaire est immuable et sa taille et son contenu ne peuvent pas être modifiés.

Alors maintenant

let myArray = [1,2,3]

produit le tableau complètement immuable. Yay!

1
nicael

Il n’ya pas de bonne réponse à cela, et c’est bizarre.

Cependant, vous pouvez empêcher la mutation accidentelle des tableaux lors de leur passage dans votre programme en appelant yourArray.unshare(). Cela provoque la copie du tableau lorsqu'il est affecté à une nouvelle variable.

1
Chuck

IMHO la solution de contournement la plus simple consiste simplement à l'envelopper dans la fermeture de la manière suivante:

let mutableElements =  [0,1,2,3]
let reallyImmutable = {[0,1,2,3]}
println(mutableElements)
for i in 0..mutableElements.count { mutableElements[i] *= -1 }
println(mutableElements)    // [0, -1, -2, -3]
println(reallyImmutable())
for i in 0..reallyImmutable().count { reallyImmutable()[i] *= -1 }
println(reallyImmutable())      // [0, 1, 2, 3]
println(reallyImmutable()[2])   // 2
let anotherImmutable = { reallyImmutable().map{ $0 * $0 } }
println(anotherImmutable())     // [0, 1, 4, 9]

Vous payez un supplément de {} sur déclaration et () pour chaque accès, mais cela fait également que votre code parle pour lui-même.

Dan the Mutable Programmer

P.S. A écrit une classe wrapper ImmutableArray .

0
dankogai