티스토리 뷰
안녕하세요 :) Zedd입니다.
오늘은 Sequence에 대해서 공부!
# Sequence
Sequence가 익숙하지 않으시다면, 혹시 Collection은 들어보셨나요?
Collection은 프로토콜이며
Swift에서 가장 유명한 Collection Type들인 Array, Set, Dictionary는 Collection프로토콜을 conform하고 있습니다.
그리고 이 Collection프로토콜은 Sequence를 conform하고 있습니다.
네! 맞아요! Sequence도 프로토콜입니다.
protocol Sequence
Sequence는 ✔️ 한번에 하나씩 단계(step)별로 진행할 수 있는 값 목록(list of values) ✔️ 입니다.
이 Sequence의 요소를 반복하는 가장 일반적인 방법은 for-in loop를 사용하는 것이죠.
let oneTwoThree = 1...3
for number in oneTwoThree {
print(number)
}
// Prints "1"
// Prints "2"
// Prints "3"
바로 이런식으로요!
# Conforming to the Sequence Protocol
제가 만든 custom type인 Zedd로
struct Zedd {}
let zedd = Zedd()
for value in zedd {} 🚨 // error! for-in loop requires 'Zedd' to conform to 'Sequence'
for-in loop를 사용할 수 없는 이유는, Zedd가 Sequence를 conform하고 있지 않기 때문입니다.
그렇다면 일단 Zedd가 Sequence를 conform하도록 해야겠네요.
struct Zedd: Sequence {}
Sequence가 요구하는 required method는
public protocol Sequence {
...
func makeIterator() -> Self.Iterator
}
makeIterator()인데요.
Interator를 만드려면 IteratorProtocol을 conform하는 타입을 만들어야 합니다.
struct ZeddIterator: IteratorProtocol {
typealias Element = Int
var current = 1
mutating func next() -> Element? {
defer { current += 1 }
return current
}
}
struct Zedd: Sequence {
func makeIterator() -> some IteratorProtocol {
return ZeddIterator()
}
}
이런식으로요!
하지만, 타입이 Sequence, IteratorProtocol 모두 conform한다면 타입 자체가 Iterator로 행동할 수 있게 되기 때문에 makeIterator()를 구현해주지 않아도 됩니다.
즉,
struct Zedd: Sequence, IteratorProtocol {
typealias Element = Int
var current = 1
mutating func next() -> Element? {
defer { current += 1 }
return current
}
}
이렇게만 해주면 끝!
let zedd = Zedd()
for value in zedd { ✅
print(value)
}
자..이제 위 코드는 컴파일에러를 일으키지 않습니다. 🎉
다만 value가 언제까지 찍힐까요?
struct Zedd: Sequence, IteratorProtocol {
var current = 1
mutating func next() -> Int? {
defer { current += 1 }
return current
}
}
그냥 무작정 +1을 더하고있기 때문에....
for loop는 끝나지 않습니다 ㅎ
요런 상황을 방지하려면,
// 방법 1
struct Zedd: Sequence, IteratorProtocol {
var current = 1
mutating func next() -> Int? {
if current > 10 { return nil }
defer { current += 1 }
return current
}
}
// 방법 2
for value in zedd {
if value > 10 { break }
print(value)
}
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
Zedd의 next쪽에다가 제한을 걸던가, for-in loop에 걸던가 하면 됩니다!
💡 Iterator에서 nil을 리턴하는것은 완료를 의미합니다.
# 컴파일러가 for-in loop를 만났을 때
자..이제 우리는 iterator도 알고.. 좀 아는 것 같습니다?
그럼 컴파일러가 for-in loop를 만났을 때 내부적으로 어떤 일들을 하는지 알아보겠습니다.
let arr = [1, 2, 3]
for value in arr { }
아주 평범한 for-in loop입니다.
컴파일러는 이때 몇가지 간단한 변환을 하게 되는데요.
var iterator = arr.makeIterator()
while let value = iterator.next() {
}
iterator를 생성하고 while루프로 변환시킨다고 합니다.
요 내용은 WWDC21 ) Meet AsyncSequence에서 본 것을 참고하여 적어봤어요 ㅎㅎ
사실 Sequence를 conform하는 타입을 만들거나 한 일이 거의 없어서 ㅎㅎ 몰랐던 부분도 알게되어서 좋네요.
틀린점이 있다면 댓글로 남겨주세요! 👻
'Swift' 카테고리의 다른 글
[Swift 5.7] if let shorthand (1) | 2022.07.09 |
---|---|
Swift 5.6 ) Introduces existential any (9) | 2022.04.03 |
Literal (0) | 2022.01.23 |
Swift ) prefix / suffix (1) | 2021.12.01 |
Swift 5.5 ) Codable synthesis for enums with associated values (0) | 2021.11.18 |
- 스위프트
- np-hard
- IOS
- Git
- github
- swift tutorial
- Accessibility
- swift delegate
- swift3
- WidgetKit
- 스위프트 문법
- Swift
- Combine
- swift array
- ios 13
- 제이슨 파싱
- actor
- 회고
- Xcode
- WKWebView
- SwiftUI
- swift 공부
- np-complete
- swift sort
- 피아노
- UIBezierPath
- iOS delegate
- WWDC
- fastlane
- FLUTTER
- Total
- Today
- Yesterday