sanichdaniel의 iOS 개발 블로그
양방향 타입추론 본문
Swift의 타입추론은 양방향으로 이루어진다고 한다. 알아보자
Bottom-up 타입 추론
타입 정보가 leaf에서 root으로 전달되는것
var x = 0
literal 0을 보고 x의 타입을 Int로 추론한다. (정수의 literal의 기본 타입은 Int이다.)
leaf인 literal이 root인 변수의 타입을 결정한다.
let age = 26 // age is of type Int
let name = "Toni" // name is of type String
let pair = (age, name) // pair is of type (Int, String)
pair 튜플의 타입은 (age, name)의 타입으로부터 결정이 된다.
타입체커는 age, name을 코드에서 찾는다.
즉 root인 pair의 타입은 leaf에 해당하는 age, name의 literal의 타입 정보로부터 전달되는것.
아래 트리는 위의 expression의 AST를 나타낸 것이다.
Top-down 타입 추론
Top-down은 반대로 root에서 leaf로 타입 정보가 전달된다.
4가지 케이스가 있다
1. literal expression
2. Implicit member expression
3. 클로져
4. 함수 호출 expression
Literal Expression
let y: Double = 2 // y is of type Double
정수 literal의 타입은 기본적으로 Int이다.
하지만 명시적으로 Double이라 타입을 적어주면, literal의 타입이 Double로 추론된다
위의 예시에서, root인 y의 타입 정보가 leaf인 literal 2의 타입을 Double 로 결정지었다. (Top - down)
배열 literal도 디폴트 타입이 Array<T>이나 Set이라 명시하면 Set<T> 타입을 얻을수 있다.
let arr = [1, 2, 3] // arr is of type Array<Int>
let mySet: Set<Int> = [1, 2, 3] // set is of type Set<Int>
위 예시에서도 root인 mySet변수에 명시적으로 Set 타입을 주었기에, leaf인 오른쪽 배열 literal의 타입도 Set으로 추론되었다.
Implicit Member Expressions
타입의 멤버를 축약된 방식 dot . 으로 접근하는걸 말한다
enum이나 타입 메서드를 접근할때 사용된다
enum Season {
case spring
case summer
case fall
case winter
}
var season = Season.summer // season is of type Season
season = .fall
season = .fall에서
.fall을 축약된 형태로 접근할수 있는것도 season변수의 타입이 Season으로 위에서 결정되었기에 가능한것이다.
root(변수 season)의 타입정보가 leaf(literal .fall)로 전달되었다.
Closures
클로져의 인자 타입과, 리턴 타입을 명시적으로 적어주지 않더라도, 클로져가 사용되는 문맥에서 타입이 자주 추론된다.
아래에서 filter() 함수는 클로져를 인자로 받는다.
클로져의 인자 n의 타입은 numbers 의 타입에 의해 추론된다
let numbers = [1, -2, 3] // numbers is of type Array<Int>
let positiveNumbers = numbers.filter { n in n >= 0 }
print(positiveNumbers) // [1, 3]
let numbers = [1.0, -2.0, 3.0] // numbers is of type Array<Double>
let positiveNumbers = numbers.filter { n in n >= 0 }
print(positiveNumbers) // [1.0, 3.0]
Overload Resoulution
함수나 operator는 overload될수 있다.
타입체커는 overload에서 어떤 함수를 사용할지 결정할때
함수의 인자의 타입과, 함수가 호출된 문맥을 둘다 확인한다.
func f() -> Int {
return 2
}
func f() -> String {
return "test"
}
let x = f() // error: ambiguous use of 'f()'
let y: Int = f() // Overload Resolution picks f: () -> Int
let z: String = f() // Overload Resolution picks f: () -> String
x의 경우에는 어떤 함수를 사용할지 결정할수 없어 에러가 난다.
하지만 y의 리턴타입은 Int가 와야하기에 첫번째 f() 함수를 사용하도록 결정이된다.
출처
'swift' 카테고리의 다른 글
WWDC: Better Apps with Value type (0) | 2020.10.25 |
---|---|
expression, statement, literal (0) | 2020.10.24 |
Operator Overloading (0) | 2020.10.16 |
빌드 타임 개선 (0) | 2020.10.14 |
Pure functions in swift (0) | 2020.10.14 |