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.
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.)
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
C'est maintenant possible.
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!
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.
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 .