Swift Operator 'Subscript' []

Swift operator `subscript` []

It looks like there are 2 questions here.

1. How can I enable subscripting on my own custom class?

To enable subscripting on your class Container you need to implement the subscript computed property like this.

class Container {
private var list : [Any] = [] // I made this private

subscript(index:Int) -> Any {
get {
return list[index]
}
set(newElm) {
list.insert(newElm, atIndex: index)
}
}
}

Now you can use it this way.

var container = Container()
container[0] = "Star Trek"
container[1] = "Star Trek TNG"
container[2] = "Star Trek DS9"
container[3] = "Star Trek VOY"

container[1] // "Star Trek TNG"

2. Can I access one element of Container that supports subscripting writing something like data[1][2]?

If we use your example no, you cannot. Because data[1] returns something of type Any. And you cannot subscript Any.

But if you add a cast it becomes possible

var container = Container()
container[0] = ["Enterprise", "Defiant", "Voyager"]
(container[0] as! [String])[2] // > "Voyager"

how to define a custom subscripting array operator which makes array elements spring into existence if necessary

This isn’t related to the subscript operator, but more a question of how to define a ??= operator. Which you can do, but it might not work quite the way you expect.

Here’s a possible implementation:

// first define the ??= operator
infix operator ??= { }

// then some pretty standard logic for an assignment
// version of ??
func ??=<T>(inout lhs: T?, rhs: T) {
lhs = lhs ?? rhs
}

This compiles, and works as you might be expecting:

var i: Int? = 1

i ??= 2 // i unchanged

var j: Int? = nil

j ??= 2 // j is now Some(2)

It will also work in combination with subscripts:

var a: [Int?] = [1, nil]

a[1] ??= 2

a[1] // is now Some(2)

I say this might not work completely as expected because of the types. a ?? b takes an optional a, and if it’s nil, returns a default of b. However it returns a non-optional value. That’s kinda the point of ??.

On the other hand, ??= cannot do this. Because the left-hand side is already determined to be optional, and an assignment operator cannot change the type only the value. So while it will substitute the value inside the optional in the case of nil, it won’t change the type to be non-optional.

PS the reason the ??= function compiles at all is because non-optional values (i.e. what you will get back from lhs ?? rhs) are implicitly upgraded to optional values if necessary, hence lhs ?? rhs, of type T, can be assigned to lhs, which is of type T?.

How do I implement custom operator [] in swift

apple docs

Subscripts enable you to query instances of a type by writing one or
more values in square brackets after the instance name. Their syntax
is similar to both instance method syntax and computed property
syntax. You write subscript definitions with the subscript keyword,
and specify one or more input parameters and a return type, in the
same way as instance methods.


Subscript is not an operator. Just a method marked with the subscript keyword.

subscript (index:Int) -> T {
return impl[index + frontCur]
}

Read this:

class MyColl {

private var someColl : [String] = []

subscript(index: Int) -> String {
get {
return someColl[index]
}
set(value) {
someColl[index] = value
}
}
}

And read this:

Swift has a well-designed and expansive suite of built-in collection types. Beyond Array, Dictionary, and the brand new Set types, the standard library provides slices, lazy collections, repeated sequences, and more, all with a consistent interface and syntax for operations. A group of built-in collection protocols—SequenceType, CollectionType, and several others—act like the steps on a ladder. With each step up, a collection type gains more functionality within the language and the standard library.

What is additional advantage of subscript use over method

Subscripts have three advantages over functions that I can think of:

  1. Familiarity. Many Swift programmers are familiar with using [] to access array elements in other languages like Python, C, C++, and Java.

  2. Terseness. If you want to access a collection element using a function, the function needs a name. Even a short name like at (which Smalltalk uses) requires more characters than []. Compare array[i] to array.at(i).

  3. Flexibility. A subscript operator can allow both reading and writing. You can even use a subscript operator on the left side of a mutating binary operator, like this:

    array[i] += 1

    Without the subscript operator, you'd need to explicitly write two separate function calls, like this:

    array.at(i, put: array.at(i) + 1)

    Or maybe use a function that takes a mutation closure, like this:

    array.at(i, update: { $0 + 1 })

Why I Cannot subscript a value of type '[String : [String]]' with an argument of type 'String.SubSequence' (aka 'Substring')?

You can simply use Dictionary's init(grouping:by:) initializer like so,

var animalsDict = Dictionary(grouping: animals) { String($0.first!) }

var animalSectionTitles = animalsDict.keys.sorted()

Output:

print(animalsDict) //["G": ["Giraffe", "Greater Rhea"], "P": ["Panda", "Peacock", "Pig", "Platypus", "Polar Bear"], "E": ["Emu"], "H": ["Hippopotamus", "Horse"], "K": ["Koala"], "L": ["Lion", "Llama"], "R": ["Rhinoceros"], "D": ["Dog", "Donkey"], "B": ["Bear", "Black Swan", "Buffalo"], "M": ["Manatus", "Meerkat"], "W": ["Whale", "Whale Shark", "Wombat"], "S": ["Seagull"], "T": ["Tasmania Devil"], "C": ["Camel", "Cockatoo"]]

print(animalSectionTitles) //["B", "C", "D", "E", "G", "H", "K", "L", "M", "P", "R", "S", "T", "W"]

Differences between subscript and functions in Swift

if you mean subscripts for custom classes, then no. looks like they are just syntactic sugar for computed properties

class IHaveASubscript<T> {
private var array: Array<T>
init() {
array = []
}
subscript (index: Int) -> T {
get {
return array[index]
}
set(newValue) {
array[index] = newValue
}
}
func elementAtIndex(index: Int) -> T {
return array[index]
}
func setElementAtIndex(index: Int, element: T) {
array[index] = element
}
}

swift: Cannot use mutating member on immutable value: subscript is get-only

You need to extend MutableCollection. A normal Collection does not support setting through subscripts, the mutable counterpart does.

extension MutableCollection where Index == Int, Element == [MyData] {
//...
}

Swift error Cannot subscript a value of type [Uint8]

The error message is misleading. The problem is that you cannot
convert an UInt8 to Int with

theDigest[theCount] as Int

You have to create a new Int from the UInt8 with

Int(theDigest[theCount])

instead.

If you don't understand the cause for some error message it is often
helpful to split a complex expression into several simple ones.
In this case

let tmp1 = theDigest[theCount]
let tmp2 = tmp1 as Int // error: cannot convert value of type 'UInt8' to type 'Int' in coercion
let tmp3 = countLeadingZeroNybbles(tmp2)

gives a constructive error message for the second line.

Swift: Subscript with Ranges error

I haven't got the book you are using, but this line:

var table = MathTable(num: 5)

Should probably be this:

var table = MathTableWithRanges(num: 5)


Related Topics



Leave a reply



Submit