Subscript syntax for adding values ​​to an array

In the Swift Programming Language book, he explicitly states:

You cannot use substring syntax to add a new element to the end of an array

The example in the book also states that even if the set of value overrides are different lengths than the range you are replacing, that's okay. For example:

var shoppingList = ["Eggs", "Milk", "Chocolate"]
shoppingList[0...2] = ["Bananas", "Apples"]
// shoppingList = ["Bananas", "Apples"]

      

which makes sense because you are replacing 3 values ​​with Banana and Apple values. However, if we did this:

var shoppingList = ["Eggs", "Milk", "Chocolate"]
shoppingList[0...2] = ["Bananas", "Apples", "Sausage", "Pear"]
// shoppingList = ["Bananas", "Apples", "Sausage", "Pear"]

      

I thought we were not allowed to use substring syntax to add a new element to the end of the array, but that looks like a loophole in this language. Can anyone explain to me why this is happening and / or if this is valid behavior or error? Thank!

+3


source to share


2 answers


When the book says, "You can't use substring syntax to add a new element to the end of an array," what it really means is, "The way it Array.subscript (index: Int) -> T

was implemented, you can't use it to add a new element to the end of the array."

subscript

is just some syntactic sugar for a property function that takes some arguments (in this case index

) and either gets or sets a value (in this case T

). But like any function, what it does might be what you want. It could set the value index

, or it could launch nuclear missiles if you wrote it that way.

As it happens, Array

defines a second overload for subscript

that deals with ranges, and that has extensibility. But the book refers specifically to the more conditional one, which just takes one index.



To demonstrate, there is an extension to Array

that defines a different version of the index, this time one that, if you specify an index extend:

, will expand the array with a new value up to the desired index:

extension Array {
    // add a new subscript with a named argument
    subscript (extending index: Int) -> T {
        get { return self[index] }
        set(newValue) {
            if index < self.endIndex {
                self[index]
            }
            else {
                let extendBy = index + 1 - self.endIndex
                self.extend(Repeat(count: extendBy, repeatedValue: newValue))
            }
        }
    }
}

var a = [1,2,3]

a[extending: 5] = 100
// a is now [1, 2, 3, 100, 100, 100]

      

+3


source


Subscript is nothing more than a function without a name. He can do whatever he can — change is possible. As with any function, if you pass in invalid parameters, it won't work.

When using an index with an array type array[index]

to set a new value, the array simply replaces the existing value with the input, so if you entered an index that doesn't already exist, it cannot replace the value and therefore will fail.

The book said something like

var array = [0, 1, 2]
array[3] = 3

      



which will give you an error indexOutOfBounds

because index 3 does not exist yet and the index does not add a new item automatically.

Suppose the implementation of this index checks to see if the index exists yet and adds it when needed. What can happen:

var array = [0, 1, 2]
array[100] = 3  // Index 100 doesn't exist -> But what to add at index 3 to 99?

      

Also every time you assign something to an array you need to do a check, which will be incredibly slow.

+2


source







All Articles