본문 바로가기

프로그래밍/Swift

[swift] 함수와 클로저

반응형

함수

매개변수 x와 y 두 값을 받아서 더하여 반환하는 함수를 아래와 같이 만들 수 있다.

 

func sum(x: Int, y: Int) -> Int {
    return x + y
}

print(sum(x: 1, y: 3)) // 4 출력

 

 

파라미터(x, y) 앞에 커스텀 전달인자를 설정할 수 있다. 아래 sum 함수의 경우 x에는 a, y에는 b라는 전달인자 이름을 설정했다. 이후 sum 함수를 호출할 때 a와 b가 전달인자 이름으로 사용된다.

 

func sum(a x: Int, b y: Int) -> Int { // 커스텀 전달인자 설정(a,b) 및 파라미터(x,y)
    return x + y
}

sum(a: 1, b: 3) // a, b 커스톰 전달인자

 

 

파라미터(x, y) 앞에 "_"를 통해 전달인자 이름을 생략하도록 정의했다. 이 경우 sum 함수를 호출할 때 인자 이름은 생략되고 값만 입력한다. 각 값은 순서에 의해 구분된다. 

 

func sum(_ x: Int, _ y: Int) -> Int { // "_" 를 통해 전달인자 이름 생략
    return x + y
}

sum(1, 3) // 전달인자 이름 생략됨

 

 

명시적일 필요가 있으면 인자 이름을 붙이고, 불필요한 경우 인자 이름을 생략한다.

 

func go(_ place: String, on day: String) -> String {
    // 암시적 인자의 매개변수: place
    // 명시적 인자 이름, 매개변수: on, day
    return "I go to \(place) on \(day)"
}

go("school", on: "Monday")

 

 

튜플

복잡한 값은 튜플을 활용할 수 있다.

튜플은 명시적인 이름을 붙여서 참조할 수 있다.

 

func rectangleCalculator(x: Double, y: Double) -> (area: Double, perimeter: Double) {
    return (area: x * y, perimeter: (x + y) * 2)
}

let result = rectangleCalculator(x: 2, y: 3) // (area: 6.0, perimeter: 10.0)
result.area // 사각형 넓이 6.0
result.perimeter // 사각형 둘레 10.0

 

 

이름을 생략하고 순서 번호로 참조할 수도 있다.

 

func rectangleCalculator(x: Double, y: Double) -> (Double, Double) {
    return (area: x * y, perimeter: (x + y) * 2)
}

let result = rectangleCalculator(x: 2, y: 3) // (6.0, 10.0)
result.0 // 사각형 넓이 6.0
result.1 // 사각형 둘레 10.0

 

 

클로저

클로저는 나중에 호출될 수 있는 코드 블록이다. 클로저 코드는 다른 스코프에서 실행되더라도 그것이 생성된 스코프에서 사용 가능한 변수나 함수 등에 접근할 수 있다.

 

 

이것을 이해하기 앞서 Nested function(중첩 함수)에 대해 알아보자.

 

func scopeA() -> Int {
    var x = 1
    func add() {
        x += 1
    }
    
    add()
    
    return x
}

 

scopeA() 함수 안에 add() 함수가 있고 add() 함수는 외부 변수인 x에 접근할 수 있다. 내부에 좀 더 복잡하거나 긴 코드가 필요할 때 사용할 수 있다.

 

 

그리고 아래와 같이 중첩 함수를 통해 변수 대신 또 다른 함수를 리턴할 수도 있다.

 

func scopeA() -> ((Int) -> Int) {
    func add(number: Int) -> Int {
        return 1 + number
    }
    
    return add
}


let a = scopeA()
a(1) // 2

 

scopeA()에 정의된 내부 함수 add(number: Int)는 외부에서 호출된다. 호출 시 외부에서 입력된 Int 1을 인자로 사용하여 계산 후 반환하게 된다. 이것을 통해 내부(스코프 A)에 정의된 함수가 외부의 값(Int 1)에 접근할 수 있는 꼴이 된다.

 

 

클로저는 이와 같은 원리를 베이스로 두어 인자로서 사용되는 코드 블록을 말한다. 아래 클로저 함수를 살펴보자.

 

func isTrue(number: Int, condition: (Int) -> Bool) -> Bool {
    return condition(number)
}

 

condition이 클로저에 해당하는 코드 블록이다. 해당 클로저는 외부에서 나중에 인자와 함께 호출되어 isTrue 함수 내부에서 실행된다.

 

 

클로저 함수는 아래와 같은 방법으로 더욱 간결하게 사용할 수 있다.

 

// 1
func isOdd(number: Int) -> Bool {
    return number % 2 != 0
}
isTrue(number: 77, condition: isOdd) // true

// 2
isTrue(number: 77, condition: { (number: Int) -> Bool in
    return number % 2 != 0
}) // true

// 3
isTrue(number: 77) { number in
    return number % 2 != 0
} // true

// 4
isTrue(number: 77, condition: {
    return $0 % 2 != 0
}) // true

 

참고: Apple Inc. “The Swift Programming Language (Swift 5.3)”. Apple Books. https://books.apple.com/hk/book/the-swift-programming-language-swift-5-4/id881256329?l=en

반응형