Language/Swift

Swift) 고차함수, 클로저

snowe 2021. 4. 16. 02:12

오늘은 들어도 까먹고 자꾸만 헷갈리는 고차함수, 클로저 개념에 대해서 한번 짚고 넘어가려 합니다.

 

자 일단 고차함수가 뭐냐..면

고차함수: '다른 함수를 전달 인자로 받거나 함수 실행의 결과를 함수로 반환하는 함수'를 뜻합니다.

자 "함수를 전달인자로 받거나, 함수 실행의 결과로 반환받는다" 라고 했죠?

 

 

음..예전에 JS 1급 객체에 대해서 포스팅 했던 이 글이 떠오르네요

 

JavaScript 기초) JS에서 함수는 1급 객체이다

JavaScript에서 함수는 1급 객체(first class object)다. 1급 객체? 그게 뭐죠? 1급 객체(First Class Object) 1급 객체란 특정 언어에서 객체를 1급 시민으로써 취급한다는 뜻입니다. 조금 다르게 표현하면? "1급.

snowee.tistory.com

네 맞습니다. Swift의 함수 또한 1급 객체입니다. 

그래서 우리는 함수를 전달 인자로 보내거나, 변수/상수로 저장 혹은 전달하거나, 함수의 반환값으로 쓸 수 있죠!(1급 객체의 특징)

 

 

 

자 근데 함수는 클로저이기도 합니다. 클로저는 또 뭘까요?

 

클로저(Closure): 클로저란 코드의 블럭입니다. 실제 우리가 알고 있는 함수는 클로저의 한 형태로, 이름이 있는 클로저입니다.

 

클로저는 기본적으로 이런 형태를 띄고 있습니다. in 이라는 키워드를 통해 정의부와 실행부를 분리해줍니다.

만약 매개변수 선언부가 없다면 in 키워드를 생략 할 수 있습니다.
{ (매개 변수들) -> 반환 타입 in
   실행 코드
}

 

Swift로 프로그래밍을 하면서 자주 만들게 되는 Alert에 action을 부여하게 되는 상황에서 우리는 클로저를 자주 목격합니다.

// 1. 처음
let action = UIAlertAction(title: String?, style: UIAlertActionStyle, handler ((UIAlertAction) -> Void)?)

// 2. 자동완성 한번
let action = UIAlertAction(title: "OK", style: .default) {
  (UIAlertAction) in
}

// 3. 자동완성 두번
let action = UIAlertAction(title: "OK", style: .default) {
  (action) in
}

 

으흠~~ 이런게 클로저였구나🥳

 

 

 

직접 코드를 짠다면 간단하게 이런 방법으로 사용할 수 있겠네요!

//MARK: -이름이 없는 클로저 이용
let numbers: [Int] = [1,2,3,4]
let reversed: [Int]

reversed = numbers.sorted(by: { (left: Int, right: Int) -> Bool in
    return left > right})

print(reversed) //[4,3,2,1]

 

코드가 이해 가시나요?

 

reversed라는 정수형 배열에, 정렬된 numbers를 넣어줄건데, 비교군에서 왼쪽으로 갈수록 더 크게 정렬할거야!(그때만 true야)

...라는 의미입니다ㅎㅎ

 

 

길게 쓰기 귀찮으니 클로저의 축약도 알아볼까요?

1.후행클로저

괄호가 많아지고 중첩되면 헷갈리는 상황들을 위해서 클로저는 아래 처럼 축약이 가능해요!

단, 함수 혹은 메서드의 맨 마지막으로 클로저를 받아왔을 경우에만!
// 후행 클로저(Trailing Closure) 사용
let reversed: [Int] = numbers.sorted() { (left: Int,right: Int) -> Bool in
  return left > right
} 

// sorted(by:) 메서드의 소괄호까지 생략 가능
let reversed: [Int] = numbers.sorted { (left: Int,right: Int) -> Bool in
  return left > right
} 

 

2.매개변수 타입, 반환 타입 생략

사용하는 메서드에서 매개 변수의 타입과 반환 타입을 이미 알고 있다면, 까이꺼 안써줘도 됩니다.

let reversed: [Int] = numbers.sorted() { (left,right) in
  return left > right
} 

 

3. return 키워드 생략, 축약된 전달 인자 이름 사용

여기서는 매개변수가 없어서 in 키워드 또한 생략해주었네요!
// 축약된 전달 인자 사용
let reversed: [Int] = numbers.sorted{
	return $0 > $1
}

// 축약된 전달 인자 사용 && return 키워드 생략
let reversed: [Int] = numbers.sorted{
	return $0 > $1
}

 

오호..엄청 짧아졌네요

그래도 코드는 가독성이 가장 중요하니까 상황에 맞게 적정선의 축약을 사용해야할 것 같습니다!

 

 

 

여기까지 고차함수와 클로저의 기본적인 개념을 한번 짚어보았습니다. 그래도 어느 정도 틀은 잡은 것 같으니 다음 글에서는 클로저를 사용한 고차함수들의 종류에 대해서 공부해보도록 하겠습니다 :)

 

 

 

참고

 

Swift의 클로저 및 고차 함수 이해하기

Swift의 클로저와 고차 함수 개념을 쉽고 명확하게 짚어 드립니다.

academy.realm.io

 

Closures — The Swift Programming Language (Swift 5.4)

Closures Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. Closures can capture and store referen

docs.swift.org