티스토리 뷰

🍏/Swift

[Swift] some, any 키워드

eungding 2022. 7. 16. 20:29
반응형

WWDC 2022 > Embrace Swift Generics 에 나오는 내용입니다. 

 


 

Feed (사료, 먹이) 를 associatedtype으로 가지는 Animal 프로토콜을 예제로 사용합니다. 

 

 

[1]  AS IS

 

Farm에 feed라는 메소드를 만들고 싶을 때, 

아래 두가지 중 하나의 방법으로 코드를 작성해줬어야했습니다. 

 

 

메소드가 좀 복잡해보입니다. 

 

[2] TO BE 

 

하지만!!  이제 opaque type인 some을 사용하여,  아래와 같이 간단한 메소드를 만들 수 있습니다. 

 

 

Swift 5.7부터는 some을 parameter type에도 쓸 수 있기 때문입니다  👏

(이전에는 프로퍼티 타입, 리턴 타입에만 쓸 수 있었음)

 

 

 

[3] some 과 any (1)

 

하지만,, some은 제약이 있는데,, 

아래와 같이 feedAll 메소드를 만들때 animals의 타입을  [some Animal] 로 해줄 수 없습니다,, 

 

 

 

왜냐면 some은 underlying type이 fixed 라서

array의 모든 element 타입이 같아야하기 때문입니다. 

 

 

우리는 different animal types 를 담고 싶습니다.

이때 any 키워드를 사용하면 어떤 타입의 animal이든 받을 수 있습니다. 

 

 

any 키워드는 이 유형이 임의의 유형의 동물을 저장할 수 있으며 런타임에 달라질 수 있음을 나타냅니다.

 The "any" keyword indicates that this type can store any arbitrary type of animal, and the underlying type of animal can vary at runtime.

 

any는 swift 5.7부터 쓸 수 있습니다. 

 

 

[any Animal] 표현은 좀 특별한데,,,

상자를 생각해보면,,,

값이 상자 안에 직접 들어갈 정도로 작은 경우도 있고

값이 상자에 비해 너무 크기 때문에, 그 값은 다른 곳에 할당되고 상자는 그 값에 대한 포인터를 저장하는 경우도 있습니다. 

 

 

이 두개를 "static type은 같으나 dynamic 타입은 다르다" 라고 표현할 수 있습니다.

 

 

이런 것을  'existential type' 이라고 부른다고 하고 

The static type any Animal that can dynamically store any concrete animal type is formally called an existential type.

 

다른 concrete type들을 사용할 수 있는 전략을 'type erasure' 라고 부른다고 하네요 

And the strategy of using the same representation for different concrete types is called "type erasure." 
The concrete type is said to be erased at compile time, and the concrete type is only known at runtime.

 

type erasure는 서로 다른 동물 값 사이의 유형 수준 구분(type-level distinction)을 제거하며, 이는 다른 동적 유형을 가진 값을 동일한 정적 유형으로 상호 교환하여 사용할 수 있게 합니다. 



[4]  some 과 any (2)

 

하지만 feedAll 을 구현하는 중,

animal의 eat을 호출하면 컴파일에러가 납니다. 

 

 

specific animal type 들 간의  type-level distinction 을 제거했기 때문에 

specific animal type 에 의존하는 모든 type relationship 을 제거한 셈입니다! 

여기에는 associated types 도 포함됩니다.

그러므로 우리는 이 동물이 어떤 종류의 Feed 를 기대하는지 알 수 없기 때문에 eat을 부를 수 없는 것입니다.

 

 

이를 해결하기 위해

specific animal type이 fixed 된 context로 돌아가야합니다. 

 

컴파일러는 any Animal을 some Animal로 컨버팅할 수 있습니다.

underlying value 를 unboxing 하고 some Animal 파라미터에 전달하는 방식으로! 

 

 

이 unboxing 기능은 정말 멋집니다!

유연한 스토리지(flexible storage)를 사용할 수 있으며 fixed type이 필요한 context로도 돌아갈 수 있게 해주기 때문입니다. 

 

This is really cool because it allows us to opt for flexible storage when we need it, while still allowing us to get back to a context where we have the full expressivity of the static type system by fixing the underlying type for the scope of a function.

 

이렇게 코드를 작성해주면 되겠습니다.

 

 

[5] some과 any 정리 

 

위에서 살펴본 것처럼

some과 any는  각각 다른 capability (능력, 역량)  를 가지고 있습니다. 

 

 

 

some을 기본으로 쓰고 임의의 (arbitrary) values를 store 해야할때 some -> any로 바꾸십시오.

 

이 접근방식을 사용하면 type erasure와 semantic limitations 에 드는 비용을

storage 유연성이 필요할 때만 지불할 수 있습니다. 

 

이것은 let constant를 기본적으로 쓰다가 mutation이 필요할 때 let -> var로 바꾸는 것과 같은

접근방식이라고 볼 수 있습니다. 

 

반응형
댓글