Immutable/Mutable Collections in Swift

Immutable/Mutable Collections in Swift


Arrays

Create immutable array

First way:

let array = NSArray(array: ["First","Second","Third"])

Second way:

let array = ["First","Second","Third"]

Create mutable array

var array = ["First","Second","Third"]

Append object to array

array.append("Forth")


Dictionaries

Create immutable dictionary

let dictionary = ["Item 1": "description", "Item 2": "description"]

Create mutable dictionary

var dictionary = ["Item 1": "description", "Item 2": "description"]

Append new pair to dictionary

dictionary["Item 3"] = "description"

More information on Apple Developer

How to change $0 to be mutable?

You don't need $0 to be mutable. map will use whatever value you return, so you can use the last map like this:

.map {$0 == "123" ? "replace" : $0}

When that map closure is run, whenever $0 matches "123", it will return replace, otherwise it will return the current value.

How do you create an immutable array in Swift?

This has changed with Xcode 6 beta 3. While arrays used to be semi-mutable, as you describe, with their elements changeable but their length fixed, now immutable arrays share the same value semantics as Dictionaries:

From the Xcode 6 beta 3 release notes:

• Array in Swift has been completely redesigned to have full value semantics like Dictionary and String have always had in Swift. This resolves various mutability problems – now a 'let' array is completely immutable, and a 'var' array is completely mutable – composes properly with Dictionary and String, and solves other deeper problems. Value semantics may be surprising if you are used to NSArray or C arrays: a copy of the array now produces a full and independent copy of all of the elements using an efficient lazy copy implementation. This is a major change for Array, and there are still some performance issues to be addressed. Please
!see the Swift Programming Language for more information. (17192555)

The original information on arrays in the Swift book was updated on 7th July 2014 to reflect the beta 3 changes. (If you're using iBooks on a Mac, as I was, you may need to delete and re-download it to pick up the 7th July update—I couldn't get the thing to update automatically.)

How does let/var resolve mutability?

For arrays and dictionaries, the let or var keyword decides whether the whole collection would be mutable or immutable. In other words, if you declare a dictionary immutable by using the let keyword, you cannot change any of its values, so the second example would not work.

In Swift deciding whether a collection will be mutable or immutable only depends on the keyword you use to declare it, so declaring an array/dictionary using the let keyword will be equivalent to declaring an immutable array (NSArray in Objective-C) while declaring it with the var keyword will give you a mutable array (NSMutableArray in Objective-C).

Immutable `var` array

What you want doesn't make sense for Array, because it is a value type with value semantics. The value of the variable is the array -- so the ability to change the variable and the ability to change the array are in a way the same thing.

Semantically there is no difference between:

myArr.append(42)

and something like (made up):

myArr = myArr.newArrayWithAppending(42)

In a way, you can imagine that any "modification" to a value type variable could be implemented as assigning a completely new value to the variable. (It's probably not done that way because it would be inefficient, but from a semantics point of view, there is no reason why it could not be implemented that way.)


The concept of "mutability" only makes sense for reference types, where the variable is a reference that points to the actual object, and the actual object can be shared between multiple references (so that "mutation" through one reference can be seen through another one).

With reference types, you can do what you want, with for example an immutable ImmutableArray class, and then if you have a var variable of type ImmutableArray, then you can construct a whole new immutable array and change the variable to point to the new array, but any particular array object cannot be "changed" as seen from a shared reference.

Mutability in Swift

There is nothing to teach. Class instances are always mutable regardless of whether you say var or let.

Collections are structs; the rules you're describing are for structs, which are a different animal. They are almost classes in Swift, but not quite; you've put your finger on a key difference. Any struct you make will behave the same way: it will be immutable through a reference declared let.

Making immutable function parameter mutable

You could either make that array available to all functions by declaring it as a property (and removing the class modifier of your function) or you could define your function's parameter as an in-out parameter. By adding the inout keyword right before the parameter's type, you can make the parameter mutable by keeping the reference to the passed array.

Nevertheless, I would recommend you to make your array into a property – simply because it's easier and, in my opinion, better maintainable.

How does one create a mutable copy of an immutable array in swift?

The problem is that self.toolbar.items is an implicitly unwrapped optional (of type [AnyObject]!) and they are always immutable. When you assign to the variable toolbarItems without explicitly stating its type, it too becomes an implicitly unwrapped optional, and thus is immutable as well.

To fix this do either:

var toolbarItems:[AnyObject] = self.toolbar.items
toolbarItems.removeAtIndex(2)

Or:

var toolbarItems = self.toolbar.items as [AnyObject]
toolbarItems.removeAtIndex(2)

Update

As of Xcode 6 Beta 5, you can update collections that are stored in optional variables, so the original code now works:

var toolbarItems = self.toolbar.items
toolbarItems.removeAtIndex(2)


Related Topics



Leave a reply



Submit