본문 바로가기

문법

[Swift] Sequence Type이란?

Sequence Type (프로토콜)

https://academy.realm.io/kr/posts/try-swift-soroush-khanlou-sequence-collection/

위의 계층 구조를 보면 모든 것들이 Sequence프로토콜을 기반으로 작성되었다는 사실을 알 수 있습니다.
Array타입을 사용할때 Sequence가 대부분의 기능을 제공합니다. map, filter뿐만아니라 Sequence안에 특정 조건을 만족하는 첫번째요소찾는 기능까지, 모두 다 Sequence프로토콜 안에 정의되어있습니다.
Sequence가 가장 단순한 것이고, 나머지는 Sequence를 기반으로 작성된것들입니다.

[정의]

  • 해당 요소에 대한 순차반복 엑세스를 제공하는 유형입니다.
    예시) 문자열 값, 배열, 컬렉션타입의 값들?

[특징]

  • 시퀀스는 한 번에 하나씩 단계별로 수행할 수 있는 값의 목록이다. 시퀀스의 요소를 반복하는 가장일반적인 방법은
    for in 루프를 사용하는것이다.
  • 즉, 반복문을 돌릴 수 있으면 Sequence Type의 프로토콜을 채택하고 있다고 볼 수 있다.
let oneTwoThree = 1...3
for number in oneTwoThree {
    print(number)
}
 

단순해 보이지만 이 기능을 사용하면 모든 시퀀스에서 수행할 수 있는 많은 작업에 접근할 수 있다.
예로 시퀀스에 특정 값이 포함되어 있는지 확인하기 위해 일치하는 항목을 찾거나 시퀀스의 끝에 도달할 때 까지
각 값을 순차적으로 테스트할 수 있다.

특정 camper가 있는지 확인해봅시다.

let campers = ["Donnie", "Minseong", "safari", "oneTool", "quokka"]
var hasQuokka = false
for camper in campers {
    if camper == "quokka" {
        hasQuokka = true
        break
    }
}
print("bugs has a mosquito: \(hasQuokka)")
 

시퀀스 프로토콜은 시퀀스 값에 대한 순차적인 접근에 의존하는 많은 공통작업에 대한 기본구현을 제공합니다.
또는 더 명확하고 간결한 코드에서 위의 예는 수동으로 반복하는 대신 모든 시퀀스가 Sequence에서 상속하는 배열의 contains메서드를 사용할 수 있습니다.

if campers.contains("quokka") {
    print("Hi! quokka Im here!")
} else {
    print("where is the quokka!")
}
 

반복 접근

:###중요###
:`Sequence 프로토콜은 반복에 의해 파괴적으로 소비되는지 여부와 관련하여 형식 준수에 대한 요구사항이 없습니다.

결과적으로 시퀀스의 여러 for-in루프가 반복을 재개하거나 처음부터 다시 시작할 것이라고 가정하지 않아야한다.

즉, 한번만 반복할 수 있음

컬렉션이 아닌 일치하는 시퀀스는 두 번째 for-in루프에서 임의의 요소 시퀀스를 생성할 수 있습니다.
`

  • 생성한 유형이 비파괴 반복을 지원하는지 확인하려면 Collection프로토콜에 대한 준수를 추가하십시오.

시퀀스 프로토콜 채택

사용자 정의 타입을 시퀀스에 따르도록하면 많은 노력없이 for-in 루핑 및 포함메소드와 같은 많은 유용한 작업이 가능힙니다.
고유한 사용자 정의 유형에 시퀀스 준수를 추가하려면 반복자를 리턴하는 makeIterator()메서드를 추가하세요

또는 유형이 자체적으로 반복할 수 있는경우 IteratorProtocol요구사항을 구현하고 sequence 및 IteratorProtocol모두에 대한 적합성을 선언하는것으로 충분합니다.

//struct Countdown: IteratorProtocol {
//    var count: Int
//
//    mutating func next() -> Int? {
//        if count == 0 {
//            return nil
//        } else {
//            defer { count -= 1 }
//            return count
//        }
//    }
//}
//
//let threeToGo = Countdown(count: 3)
//for index in threeToGo { // error: For-in loop requires 'Countdown' to conform to 'Sequence'
//    print(index)
//}
 

시퀀스 프로토콜을 채택하지않고는 에러가발생합니다. 반복문의 range조건에는 시퀀스 요소만 들어갈 수 있기때문입니다.
그래서 아래 예시에서는 에러가 나지않는걸 볼 수 있습니다.

struct Countdown: Sequence, IteratorProtocol {
    var count: Int
    
    mutating func next() -> Int? {
        if count == 0 {
            return nil
        } else {
            defer { count -= 1 }
            return count
        }
    }
}

struct Countdown2 {
    var count: Int
}

let threeToGo = Countdown(count: 3)
print(threeToGo)
for index in threeToGo {
    print(index)
}

for index in Countdown2(count: 3) {
    print(index)
}
 

성능에대한 예상은 ?

시퀀스는 O(1)에서 반복자를 제공해야합니다.
시퀀스 프로토콜은 요소 액세스에 대한 다른 요구사항을 만들지 않으므로 달리 문서화되지않는 한 시퀀스를 통과하는 루틴은 O(n)으로 간주되어야 합니다.

Reference