Swift Arrays - Beta 3 (Hooray!)

I should probably have written this sooner as it has been 10 days since Beta 3 was released, but I've only just noticed that there is a bit of traffic still coming in about Swift Arrays from my earlier posts about the array semantics in the first Swift betas. The short version is that I'm very happy with the new Swift Arrays in Beta 3 which have full value semantics (optimised with copy on write under the hood). The syntax for declaring arrays has also changed which is fine although I didn't have a particular problem with the old syntax. Be sure to update the Swift iBooks (delete and download again) as there are some significant changes.

The copy() and unshare() functions are gone because unshare has essentially become the default behaviour (although contents changes not just length changes now trigger the copy so copy is not needed either).

Semantic Changes

  1. Arrays are no longer reference types. You can treat every assignment, argument pass and function return as if it were a copy.
  2. Changing the contents of an array is no longer permitted when the array is declared constant with let.

In this example you can see the copy-on-write (CoW) behaviour using the identity operator (=== which I wouldn't recommend you doing in real code to affect behaviour on the CoW status but it enables us to observe the CoW). In the example it doesn't make any difference if a is declared with let or var but b must be declared as var otherwise you will get a compile time error because the contents change.

    Note that if the array contains objects (of classes) the objects themselves are fully accessible and can be mutated just as with any object of that class even if the array is declared with let. What you can't do is change or reorder which objects are within the array.

    With structs, dictionaries and other value types they cannot be mutated when within an array declared with let although they can be copied to a variable. This code would give a compile error if e was declared with let rather than var.

    Syntactic Changes

    The syntax of the explicit declaration of array (and dictionary) types has changed in beta 3.

    For arrays this doesn't actually make much difference but it cleans up the Dictionary type syntax a lot and keeps the Array syntax consistent with that so it is definitely a positive change.


    Not everybody[article removed - google cache - archived text[1]] is happy with the new Array behaviour and that post was discussed on HackerNews. The argument starts with this statement:

    Now aliasing an array will cause the array to be copied. Isn’t that weird?

    It goes on to discuss Apple describing it as Copy on Write but the real problem with the statement and the rest of the argument is describing the assignment of one array to another as "aliasing". From my point of view this is completely the wrong way to look at the the behaviour. The behaviour is as a value type copy on assign. Unless you dig in with the === identity operator or deal with massive arrays and monitor the performance you would never know that the behaviour is actually Copy on Write. So almost all[0] those copies get optimised away without changing the semantics.

    From my point of view the rest of the argument is based on this wrong conception of assignment of value types (arrays, dictionaries, structs, strings and basic types) in Swift.

    [0] Copy on Write will avoid a copy every time you pass a array but don't use it again in the calling function OR it is not modified in the callee and every time you return an array that was local OR that is a property that won't change before the return result is deallocated. Sure you can write code that forces lots of copies but generally well structured code won't do that.

    [1] I have captured a copy of the article from the Google cache as I don't know how long the Google cache link will be live. The intention is to not misrepresent the argument made in the article.