야곰의 스위프트 프로그래밍 - 함수형 프로그래밍과 스위프트
함수형 프로그래밍과 스위프트
클로저
클로저는 참조 타입. Swift에서 클래스와 클로저는 참조 타입. 나머지는 값 타입.
자동 클로저
- 자동 클로저는 전달 인자를 갖지 않는다.
- 자동 클로저는 호출되었을 때 자신이 감싸고 있는 코드의 결과값을 반환한다.
- 자동 클로저는 클로저가 호출되기 전까지 클로저 내부의 코드가 동작하지 않으므로 연산을 지연시킬 수 있다.
- 자동 클로저 속성을 부여한 매개변수는 클로저 대신에 실행 결과 타입을 전달인자로 받게 되며, 이것이 자동 클로저 매개변수에 전달되면 매개변수가 없는 결과 값의 타입을 반환하는 클로저로 변환해준다.
var strings = ["a", "b", "c"] |
옵셔널 체이닝과 빠른종료
빠른종료
guard
문의 조건에는Bool
타입이 오므로, 옵셔널 바인딩의 역할을 하지 않을 때도 빠른 종료를 위해 사용할 수 있다.- 쉼표를 사용하여 추가 조건을 나열할 수 있으므로, AND 연산과 같은 결과를 낸다.
- 제어문 전환 명령어를 사용해야 하므로 특정 블록 내부에 위치하지 않는다면 사용이 제한된다.
맵, 필터, 리듀스
Swift는 함수를 일급 객체로 취급. 그러므로 함수를 다른 함수의 전달 인자로 사용할 수 있음.
고차함수 : 매개 변수로 함수를 갖는 함수
맵
자신을 호출할 때 매개변수로 전달된 함수를 실행하여 그 결과를 다시 반환해주는 함수
Sequence
, Collection
프로토콜을 준수하는 타입과 옵셔널은 맵을 사용할 수 있음
기존 데이터를 변형하는 데 많이 사용함
for-in
구문과 비교하여 코드 재사용 측면과 컴파일러 최적화 측면에서 유리하며, 다중 스레드 환경에서 사이드 이펙트를 방지할 수 있다.
필터
컨테이너 내부의 값을 걸러서 추출하는 역할을 하는 고차함수
특정 조건에 맞게 걸러내는 역할을 할 수 있음. 전달되는 함수 객체의 반환값이 Bool
이므로 필터링될 조건에 대해 서술함
리듀스
컨테이너 내부의 컨텐츠를 하나로 합하는 기능을 실행하는 고차함수
적절하게 활용하면 코드의 양을 줄이면서, 보기 좋은 코드를 작성할 수 있음.
모나드
특정한 상태로 값을 포장. Swift에서는 옵셔널이 모나드를 구현한 형태. 값이 있을지 없을지 모르는 상태 속에 포장.
컨텍스트
컨텐츠를 담은 어떤 것
// Swift의 옵셔널 타입 정의 |
옵셔널에 값이 있다면 열거형의 .some
케이스의 값을 갖게 됨, 값이 없다면 열거형의 .none
케이스 값을 갖게 됨
옵셔널을 추출한다는 것은 .some
케이스의 연관 값을 꺼내오는 것
옵셔널은 some
과 none
두 가지의 컨텍스트를 가짐
- 컨텍스트는 2라는 값을 가지고 있다 :
some
컨텍스트 - 컨텍스트는 존재하지만 내부에 값이 없다 :
none
컨텍스트
함수객체
map
함수를 적용할 수 있는 컨테이너 타입. Array
, Dictionary
, Set
등등 많은 컬렉션 타입은 함수객체임.
extension Optional { |
옵셔널에 map
함수를 호출하면, some
컨텍스트인지 none
컨텍스트인지 확인함
some
컨텍스트이면 컨텍스트에 들어있는 컨텐츠를 가지고 인자로 전달된 함수를 수행한 후 컨텍스트에 다시 포장하여 반환none
컨텍스트이면none
컨텍스트를 반환
모나드
값이 있을 수도 있고 없을 수도 있는 컨텍스트를 갖는 함수객체 타입
옵셔널(모나드)에서의 flatMap
func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
Optional
인스턴스가nil
이 아닐 때 주어진 클로저를 평가하는데, 매개변수로 래핑되지 않은 값을 넘긴다.내부의 값을 알아서 더 추출해주어 내부에 포장된 값도 추출해낼 수 있다
let a: Int? = 3 let b = a.map { Optional($0) } let c = a.flatMap { Optional($0) } print(b) // Optional(Optional(3)) print(c) // Optional(3)
map
에서U == Int?
이므로 결과의 타입은Int??
임flatMap
에서U? == Int?
이므로 결과의 타입은Int?
임
시퀀스에서의 flatMap
func flatMap<SegmentOfResult>(_ transform: (Self.Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
- 시퀀스의 각 요소에 주어진 변형을 호출하여 이어진 결과를 포함하는 배열을 반환
- [[1, 2], [3, 4]]에 호출하여 [1, 2, 3, 4] 와 같이 만들 수 있는 메소드. 내부의 값을 1차원적으로 펼쳐놓음
func flatMap<ElementOfResult>(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
- 시퀀스의 각 요소에 주어진 변형을 호출하여
nil
이 아닌 결과를 포함하는 배열을 반환 - [“1”, “2”, nil, “5”]에 호출하여 [1, 2, 5]와 같이 만들 수 있는 메소드
- Swift 4.1에서
compactMap
으로 이름이 바뀜
- 시퀀스의 각 요소에 주어진 변형을 호출하여
옵셔널 체이닝, 옵셔널 바인딩, 플랫맵 등은 모나드와 관련된 연산