1. Subscripts πŸ‘©β€πŸ’»

Classes, Structures, Enumerations λŠ” 이것듀이 가지고 μžˆλŠ” Collection, List, Sequence 와 같은 member elements에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ 단좕킀인 Subscriptsλ₯Ό μ •μ˜ν•  수 μžˆλ‹€.

ν•˜λ‚˜μ˜ Type 에 μ—¬λŸ¬ 개의 Subscripts λ₯Ό μ •μ˜ν•  수 있으며, Subscripts 에 μ „λ‹¬ν•˜λŠ” index 의 Type 에 따라 overload 처리 ν•œλ‹€. λ˜ν•œ Subscripts λŠ” 단일 μ°¨μ›μœΌλ‘œ μ œν•œλ˜μ§€ μ•Šκ³  Custom Type에 맞좰 μ—¬λŸ¬ 개의 νŒŒλΌλ―Έν„°λ‘œ Subscriptsλ₯Ό μ •μ˜ν•  수 μžˆλ‹€.

1. Subscript Syntax

Syntax

subscript(index: Int) -> Int {
    get {
        // Return an appropriate subscript value here.
    }
    set(newValue) {
        // Perform a suitable setting action here.
    }
}

Computed Properties 와 λ§ˆμ°¬κ°€μ§€λ‘œ getter와 optional setterλ₯Ό μ œκ³΅ν•˜λ©°, setter 의 Parameter λ₯Ό μƒλž΅ν•˜κ³  κΈ°λ³Έκ°’μœΌλ‘œ newValueλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.
λ˜ν•œ Computed Properties 와 λ§ˆμ°¬κ°€μ§€λ‘œ setter 의 Parameter λŠ” λ°˜λ“œμ‹œ Return Type κ³Ό λ™μΌν•΄μ•Όν•˜λ―€λ‘œ λ³„λ„μ˜ Type을 λͺ…μ‹œν•  수 μ—†μœΌλ©°, Read-Only Computed Properties와 λ§ˆμ°¬κ°€μ§€λ‘œ Read-Only SubscriptsλŠ” get ν‚€μ›Œλ“œμ™€ μ€‘κ΄„ν˜Έλ₯Ό μƒλž΅ν•  수 μžˆλ‹€.


λ‹€μŒμ€ μ •μˆ˜μ˜ n-times-table을 ν‘œμ‹œν•˜κΈ° μœ„ν•΄ TimesTable Structureλ₯Ό μ •μ˜ν•œλ‹€. Subscripts λŠ” Read-Only Subsscripts둜 κ΅¬ν˜„λ˜μ—ˆλ‹€.

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
(0...10).forEach { print(threeTimesTable[$0], terminator: "  ") }
0  3  6  9  12  15  18  21  24  27  30  

2. Subscript Usage

Subscripts λŠ” κ΅¬ν˜„ν•˜λ €λŠ” Classes, Structures, Enumerations 에 μ ν•©ν•œ ν˜•νƒœλ‘œ 자유둭게 κ΅¬ν˜„μ΄ κ°€λŠ₯ν•˜λ‹€.
λ”°λΌμ„œ, Subscripts 의 μ •ν™•ν•œ μ˜λ―ΈλŠ” context에 따라 달라진닀. 일반적으둜 Subscripts λŠ” Collection, List, Sequence의 member elements에 μ ‘κ·Όν•˜κΈ° μœ„ν•œ μš©λ„λ‘œ μ‚¬μš©λœλ‹€.

  • Subscripts in Dictionary

Subscripts λ₯Ό μ΄μš©ν•΄ 값을 μ‘°νšŒν•˜κΈ°

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
print("The number of legs of ant is \(numberOfLegs["ant"]!).")
// The number of legs of ant is 6.

Subscripts λ₯Ό μ΄μš©ν•΄ 값을 μ €μž₯ν•˜κΈ°

numberOfLegs["bird"] = 2
print(numberOfLegs)  // ["spider": 8, "ant": 6, "cat": 4, "bird": 2]

Dictionary의 key-valueλŠ” λͺ¨λ“  keys κ°€ values λ₯Ό 갖지 μ•ŠλŠ” 것을 λͺ¨λΈλ‘œ ν•˜κΈ° λ•Œλ¬Έμ— Optional Return Type을 μ·¨ν•˜λ―€λ‘œ Optional Subscriptsλ₯Ό μ‚¬μš©ν•œλ‹€.

3. Subscript Options

Subscripts λŠ” Parameters 의 νƒ€μž…μ΄λ‚˜ 개수, Return Type 을 자유둭게 μ •μ˜ν•  수 μžˆλ‹€.
심지어 ν•¨μˆ˜μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ Variadic Parameters 와 Default Parameter Values μ—­μ‹œ κ°€λŠ₯ν•˜λ‹€.

단, In-Out Parameters λŠ” μ‚¬μš©ν•  수 μ—†λ‹€.


struct Matrix {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    func indexIsValid(row: Int, column: Int) -> Bool {
        row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}
  • grid : μ™Όμͺ½ μƒλ‹¨μ—μ„œ μ‹œμž‘ν•΄ 였λ₯Έμͺ½ ν•˜λ‹¨μœΌλ‘œ μ§„ν–‰λ˜λŠ” ν–‰λ ¬μ˜ 평면화 버전.
  • indexIsValid : row 와 column 이 유효 λ²”μœ„μΈμ§€λ₯Ό 평가.
  • subscript get : κ°’μ˜ μœ νš¨μ„± 검사λ₯Ό μœ„ν•΄ assertion 을 포함. grid 의 값을 μ°Ύμ•„ λ°˜ν™˜.
  • subscript set : κ°’μ˜ μœ νš¨μ„± 검사λ₯Ό μœ„ν•΄ assertion 을 포함. grid 에 값을 μ €μž₯.


var matrix = Matrix(rows: 2, columns: 2)
print(matrix)   // Matrix(rows: 2, columns: 2, grid: [0.0, 0.0, 0.0, 0.0])

μƒμ„±λœ grid λ₯Ό μ‹œκ°ν™” ν•˜λ©΄ μ•„λž˜μ™€ κ°™λ‹€.

SubscriptMatrix01


Subscripts λ₯Ό μ΄μš©ν•΄ 값을 μ €μž₯ν•΄λ³΄μž.

matrix[0, 1] = 1.5
matrix[1, 0] = 3.2

SubscriptMatrix02

μœ νš¨ν•˜μ§€ μ•Šμ€ 값을 μ €μž₯ν•˜λ € ν•  경우 assertion 에 μ˜ν•΄ μ•„λž˜μ™€ 같이 μ—λŸ¬κ°€ λ°œμƒλœλ‹€.

matrix[2, 0] = 3.2  // __lldb_expr_13/1. Subscripts.xcplaygroundpage:45: Assertion failed: Index out of range


이제 μœ„μ—μ„œ μ €μž₯ν•œ 데이터λ₯Ό Subscripts λ₯Ό μ΄μš©ν•΄ μ‘°νšŒν•΄λ³΄μž.

print(matrix[1, 0]) // 3.2

2. Type Subscripts

Subscripts μ—­μ‹œ Properties, Methods 와 λ§ˆμ°¬κ°€μ§€λ‘œ Instance 뿐만 μ•„λ‹ˆλΌ Type 자체의 Subscriptsλ₯Ό μ •μ˜ν•  수 μžˆλ‹€.

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
    static subscript(n: Int) -> Planet {
        Planet(rawValue: n)!
    }
}
let earth = Planet(rawValue: 3)!
print(earth)    // earth

let mars = Planet[4]
print(mars)     // mars
  • Initializers λ₯Ό μ΄μš©ν•΄ new Instance β€˜earth’ λ₯Ό μƒμ„±ν–ˆλ‹€.
  • Subscripts λ₯Ό μ΄μš©ν•΄ getterκ°€ new Instance β€˜mars’ λ₯Ό μƒμ„±ν–ˆλ‹€.


print(type(of: earth))  // Planet
print(type(of: mars))   // Planet

결과물은 λ™μΌν•˜μ§€λ§Œ, Subscriptsλ₯Ό μ΄μš©ν•˜λ©΄ 맀번 Initializersλ₯Ό μ‚¬μš©ν•  ν•„μš” 없이 Arraysλ‚˜ Dictionaries에 μ ‘κ·Όν•˜λ“― new Instanceλ₯Ό 생성할 수 μžˆλ‹€.




Reference

  1. β€œSubscripts.” The Swift Programming Language Swift 5.7. accessed Nov. 28, 2022, Swift Docs Chapter 11 - Subscripts.