🔥 함수와 클로저

797자
9분

Swift에서는 func 키워드를 사용하여 함수를 선언할 수 있어요. 함수를 호출할 때는 함수 이름 뒤, 괄호 안에 인자 목록을 적으면 됩니다. 매개변수 이름과 타입을 함수의 반환 타입과 구분하기 위해 -> 기호를 사용하죠.

func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday")
swift

기본적으로 함수는 매개변수 이름을 인자의 레이블로 사용합니다. 매개변수 이름 앞에 사용자 정의 인자 레이블을 작성하거나 _를 사용하여 인자 레이블을 생략할 수 있어요.

func greet(_ person: String, on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
swift

튜플을 사용하여 복합 값을 만들 수 있습니다. 예를 들어, 함수에서 여러 값을 반환할 때 튜플을 활용할 수 있죠. 튜플의 요소는 이름이나 번호로 참조할 수 있어요.

func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]  // 최소값을 배열의 첫 번째 요소로 초기화합니다.
    var max = scores[0]  // 최대값을 배열의 첫 번째 요소로 초기화합니다.
    var sum = 0  // 합계를 0으로 초기화합니다.
 
    for score in scores {
        if score > max {
            max = score  // 현재 점수가 최대값보다 크면 최대값을 업데이트합니다.
        } else if score < min {
            min = score  // 현재 점수가 최소값보다 작으면 최소값을 업데이트합니다.
        }
        sum += score  // 현재 점수를 합계에 더합니다.
    }
 
    return (min, max, sum)  // 최소값, 최대값, 합계를 튜플로 반환합니다.
}
let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum)  // "120"을 출력합니다.
print(statistics.2)  // "120"을 출력합니다.
swift

함수는 중첩될 수 있어요. 중첩된 함수는 외부 함수에서 선언된 변수에 접근할 수 있습니다. 중첩 함수를 사용하여 길거나 복잡한 함수의 코드를 구성할 수 있죠.

func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5  // 외부 함수의 변수 y에 접근하여 값을 증가시킵니다.
    }
    add()  // 중첩 함수 add()를 호출합니다.
    return y
}
returnFifteen()  // 15를 반환합니다.
swift

함수는 일급 타입입니다. 이는 함수가 다른 함수를 값으로 반환할 수 있다는 것을 의미해요.

func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)  // 8을 반환합니다.
 
swift

함수는 인자로 다른 함수를 받을 수 있어요.

func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: lessThanTen)  // true를 반환합니다.
swift

함수는 사실 클로저의 특별한 경우입니다. 클로저는 나중에 호출할 수 있는 코드 블록이에요. 클로저의 코드는 클로저가 생성된 범위에서 사용할 수 있는 변수와 함수에 접근할 수 있습니다. 클로저가 실행될 때 다른 범위에 있더라도 말이죠. 이는 중첩 함수에서 이미 확인했던 내용이에요. 중괄호({})로 코드를 감싸서 이름 없는 클로저를 작성할 수 있습니다. in 키워드를 사용하여 인자와 반환 타입을 본문과 구분하죠.

numbers.map({ (number: Int) -> Int in
    let result = 3 * number
    return result
})
swift

클로저를 더 간결하게 작성하는 몇 가지 옵션이 있어요. 클로저의 타입이 이미 알려진 경우, 예를 들어 대리자의 콜백인 경우, 매개변수의 타입이나 반환 타입 또는 둘 다를 생략할 수 있습니다. 단일 문장 클로저는 암시적으로 유일한 문장의 값을 반환하죠.

let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
// "[60, 57, 21, 36]"을 출력합니다.
swift

매개변수 이름 대신 번호로 매개변수를 참조할 수 있어요. 이 접근 방식은 특히 매우 짧은 클로저에서 유용합니다. 함수의 마지막 인자로 전달된 클로저는 괄호 바로 뒤에 나타날 수 있죠. 클로저가 함수의 유일한 인자인 경우, 괄호를 완전히 생략할 수 있어요.

let sortedNumbers = numbers.sorted { $0 > $1 }
print(sortedNumbers)
// "[20, 19, 12, 7]"을 출력합니다.
swift

클로저는 Swift에서 강력하고 유연한 기능이에요. 클로저를 사용하면 코드를 더 간결하고 표현력 있게 작성할 수 있습니다. 클로저는 함수형 프로그래밍 패러다임을 지원하며, 고차 함수와 함께 사용될 때 매우 강력해지죠.

다음은 클로저의 실제 사용 예시입니다.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
 
func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames는 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]입니다.
swift

위 코드에서 backward(_:_:) 함수는 sorted(by:) 메서드의 by 매개변수에 전달되었어요. 이를 통해 문자열 배열을 역순으로 정렬할 수 있죠.

클로저 표현식 구문을 사용하면 이를 더 간결하게 작성할 수 있습니다.

reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})
swift

클로저의 타입이 이미 알려져 있기 때문에 매개변수 타입과 반환 타입을 생략할 수 있어요.

reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
swift

단일 표현식 클로저에서는 return 키워드도 생략할 수 있죠.

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
swift

연산자 메서드를 사용하면 더 짧게 표현할 수 있어요.

reversedNames = names.sorted(by: >)
swift

이렇게 클로저는 코드를 간결하고 표현력 있게 작성할 수 있게 해줍니다. 클로저는 Swift의 강력한 기능 중 하나이며, 함수형 프로그래밍 패러다임을 지원하죠. 클로저를 잘 활용하면 더 간결하고 가독성 높은 코드를 작성할 수 있습니다.