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!
source to share
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]
source to share
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.
source to share