본문 바로가기
iOS/Swift

Swift 함수③ - 함수 표기 방법/일급 객체 함수/함수 타입/중첩 함수

 

 

 

 

Swift 함수 마지막 포스팅입니다!
혹시 함수①, 함수② 포스팅을 보지 못하셨다면

보고 오시는 걸 추천해 드리며 바로 시작하겠습니다!

 

 

 

 

 

 

 

1. 함수를 표기하는 방법 - 식별자(Signature)

 

 

애플 공식 문서에 함수를 검색하면

다음과 같이 함수 이름이 작성된 것을 볼 수 있습니다.

 

 

print(_:separator:terminator:)
print(_:separator:terminator:)

 

 

 

이번 포스팅에서는 이처럼

함수를 표기하는 방법에 대해서 먼저 알아보겠습니다.

 

 

 

함수 관련 첫 번째 포스팅에서 알아본 전달 인자 레이블

함수를 호출할 때만 사용하는 것이 아니라,
함수를 표기하고 식별할 때도 사용합니다.

 

 

 

예시를 보며 함수를 표기하는 방법에 대해 알아보겠습니다.

 

 

1-1. 매개변수가 한 개 있는 함수

 

 

func greeting(name: String) {
    print("안녕하세요. \(name)님")
}

 

 

 

괄호 안에 전달 인자 레이블과 콜론을 작성해서 함수를 표기합니다.

 

 

//함수 표기 방법
greeting(name:)

 

 

 

 

 

 

 

 

만약 전달 인자 레이블을 생략했다면,

 

 

func greeting(_ name: String) {
    print("안녕하세요. \(name)님")
}

 

 

함수를 표기할 때도 다음과 같이 표기합니다.

 

 

//함수 표기 방법
greeting(_:)

 

 

 

 

 

 

 

 

 

1-2. 매개변수 여러 개 있는 함수

 

func greeting(name: String, age: Int) {
    print("안녕하세요. \(name)님")
}

 

 

전달 인자 레이블과 콜론을 차례로 나열하여 다음과 같이 표기합니다.
이때 쉼표는 작성하지 않습니다!

 

 

//함수 표기 방법
greeting(name:age:)

 

 

 

 

 

 

 

 

 

2. 일급 객체 함수

 

 

Swift에서 함수는 일급 객체로 취급합니다.

 

 

일급 객체가 무엇인지 단어의 사회적 유례를 보겠습니다.

 


일급 객체는 영어로 first class citizen입니다.
이를 직역하면 1등 시민입니다.

1등 시민은 사회적으로 차별받지 않고 자유로운 시민을 의미합니다.

 

 

 

네이버 영어사전

 


그에 반면 2등 시민(second class citizen)은

제약이 있고 차별을 받는 시민을 말합니다.

 

 

 

 

 

이러한 사회적 정의를 기반으로 이해하면,
일급 객체(first class citizen)는 어떤 특별한 혜택을 받는 것이 아닌
‘사용할 때 다른 요소들과 아무런 차별이 없다.’는 뜻으로 이해할 수 있습니다!

 

 

 

함수가 일급 객체로 취급되기 위해서는 일급 객체 조건을 모두 충족해야 하며,
Swift에서 함수는 일급 객체 조건을 모두 충족하기 때문에 일급 객체로 분류됩니다.

 


지금부터 일급 객체 함수의 특성에 대해서 몇 가지를 살펴보도록 하겠습니다.

 

 

 

 

 

 

 

 

 

 

 

2-1. 변수나 상수에 함수 대입할 수 있음

 

 

일급 객체 함수의 특성 중 처음으로 알아볼 내용은

함수를 변수나 상수에 대입할 수 있다는 것입니다.

 


이는 다음과 같이 함수에 인자값을 넣어 실행하고,

그 결과를 상수에 대입하는 형태가 아니라

 

 

func introduce(age: Int) -> String {
    return "저는 \(age)살 입니다. "
}

let hongGilDong = introduce(age: 3) //함수 실행 결과를 상수에 대입

 

 

다음과 같이 함수 자체를 대입할 수 있다는 의미입니다.

 

 

let cheolSu = introduce // cheolSu 상수에 introduce 함수가 할당됨

 

 

위 코드를 보면 cheolSu 상수에

introduce 함수 자체를 대입하고 있습니다.

 

 

 

이렇게 함수를 변수나 상수에 대입하는 과정만으로는

함수가 실행되지 않으며 다음과 같이

 

 

cheolSu(5)

 

 

 함수가 대입된 변수나 상수를 함수처럼 호출해야

비로소 함수가 실행됩니다.

 

 

 

 

함수의 실행 결괏값을 대입한 hongGilDong

함수 자체를 대입한 cheolSu의 타입을 보면
타입 자체가 다르다는 것을 알 수 있습니다.

 

 

 

타입 비교

 

 

 

cheloSu처럼 함수 자체를 대입한 경우에는

일반적인 문자열, 배열 등과는 전혀 다른

함수 타입(Function Types)이 됩니다.

 

 

 

변수에 정수를 대입하면 Int 타입,

문자열을 대입하면 String 타입이 되는 것처럼

변수에 함수를 대입하면 함수 타입이 되는 겁니다.

 

 

 

 

 

 

함수 타입은 다음과 같은 형태로 나타냅니다.

 

함수 타입

 

 

함수를 정의할 때 반환 타입이 없으면 반환 타입을 생략할 수 있지만,

함수 타입에서는 생략할 수 없습니다!

 


실제 예시를 보면서 함수 타입에 익숙해져 보겠습니다.

 

 

 

 

①매개변수가 없는 경우

 

 

func noParameter() {}

 

 

위 함수는 매개변수와 반환이 없는 함수입니다.

이 함수를 함수 타입으로 표현하면 다음과 같습니다.

 

 

() -> ()

 

 

Playground
Playground

 

 

 

 

 

 

②매개변수가 있는 경우

 

 

func thereIsParameter(first: String) {}

 

 

매개변수가 한 개 있는 함수는
다음과 같이 함수의 타입을 표현합니다.

 

 

(String) -> ()

 

 

Playground
Playground

 

 

 

 

만약 여러 개의 매개변수가 있다면

다음과 같이 타입만 나열하여 표현합니다.

 

Playground
Playground

 

 

 

 

 

그렇다면 함수 타입은 언제 사용할 수 있을까요?

 

 

 

Swift에서는 매개변수의 개수가 다르면

같은 이름의 함수를 만들 수 있습니다.

 

 

func hello() {
    print("안녕하세요")
}

func hello(name: String) {
    print("안녕하세요 \(name)")
}

 

 

이때 함수 자체를 상수에 대입하면

 

 

let meet = hello

 

 

대입된 함수가 위쪽에 있는 hello() 함수인지 아래쪽에 있는 hello(name:) 함수인지
정확하게 판단할 수 없으므로 오류가 발생합니다.

 

 

error

 

 

 

이럴 경우, 방금 배운 함수 타입을 작성해서

입력받을 값의 타입을 명확하게 해주거나

 

 

//①타입 어노테이션
let meet:() -> () = hello

 

 

이번 포스팅 가장 처음에 알아본 것처럼 함수를 표기하면 오류가 해결됩니다.

 

 

//②함수 식별자
let meetHongGilDong = hello(name:)

 

 

 

 

 

 

 

 

 

 

 

 

2-2. 함수의 반환 타입으로 함수 사용 가능

 

 

두 번째로 알아볼 특성은

함수의 반환 타입으로 함수를 사용할 수 있다는 내용입니다.

 

예시를 보겠습니다.

 

 

func first() -> String {
    print("first 함수가 실행됩니다")
    return "first function"
}

func second() -> () -> String {
    return first
}

 

 

예시 코드를 보면 second 함수가 first 함수를 반환하고 있습니다.

 

 

 

second 함수를 자세히 보면

 

second 함수 해석

 

 

 함수의 반환 타입이 first 함수의 타입과 동일한

 

() → String

 

으로 정의됩니다.

 

 

 

 

즉, second 함수의 반환 타입과

first 함수 타입과 같기 때문에 다음과 같이

 

 

let doing = second()

 

 

doing 상수에 second 함수의 실행 결과를 할당하면,
second 함수의 반환 값인 first 함수가 할당됩니다.

 

 

따라서 다음과 같이 doing을 실행하면

 

 

 

 

first 함수가 실행됩니다.

 

 

 

 

 

 

 

 

 

2-3. 함수의 매개변수로 함수를 사용할 수 있음

 

 

Swift에서는 다른 함수의 매개변수로 함수를 전달할 수도 있습니다. 

 

func calc(base: Int, success: () -> (), fail: () -> ()) -> Int {
    if base == 0 {
        fail()
        return 0
    }
    defer {
        success()
    }
    return base/10
}

 

 

calc함수를 자세히 보면 함수를 매개변수로 받기 위해

매개변수 타입을 함수 타입으로 작성해준 것을 볼 수 있습니다.

 

 

 

 

 

 

 

이렇게 되면 다음과 같이 전달인자로 함수를 전달할 수 있습니다.

 

func printSuccess() {
    print("성공")
}

func printFail() {
    print("실패")
}

calc(base: 30, success: printSuccess, fail: printFail)

 

 

 

그런데 위 예시 코드에서 printSuccess 함수와 printFail 함수는

단순히 다른 함수에 전달되는 용도로 정의되었기 때문에

재사용성이 낮아질 수가 있습니다.

 

 

 

이런 문제를 해결하고자

Swift에는 익명 함수인 클로저를 지원합니다.

 

 

 

클로저에 대해서는 다음 포스팅에서 자세히 다룰 예정이라

지금은 아래 코드를

 

 

calc(base: 30, success: printSuccess, fail: printFail)

 

 

클로저 형태 어떻게 표현하는지만 보고 넘어가도록 하겠습니다.

 

 

//클로저 사용
calc(base:30,
    success: {
        () -> () in
        print("성공")
    },
    fail: {
        () -> () in
        print("실패")
    }
)

 

 

 

 

 

 

 

 

 

3. 중첩 함수(Nested Functions)

 

 

마지막 내용입니다. Swift는 함수 안에 함수를 중첩하여 선언할 수 있습니다.

이렇게 중첩하여 작성된 함수를 중첩 함수라고 하며, 예시 코드를 보겠습니다.

 

 

func outer() {
    func inner() {
    }
}

 

 

outer 함수 내부에 inner 함수를 선언했습니다.

 


예시에 있는 inner 함수처럼 함수 내에 작성된 함수는 내부 함수(Inner Function),
outer 함수처럼 내부 함수를 포함하는 바깥쪽 함수는 외부 함수(Outer Function)라고 합니다.

 

 

 

내부 함수는 자신을 포함하고 있는 외부 함수 안에서만 호출할 수 있습니다.

 


따라서 inner 함수는 오로지 outer 함수 내부에서만 호출이 가능합니다.

 

 

func outer() {
    func inner() {
    }
    inner() //사용가능
}
inner() //Error

 

 

 

 

 

하지만 일급 함수 특성 중 하나인
함수의 반환 타입으로 함수를 사용 가능하다는 내용을 활용하면 다음과 같이

 

 

func outer() -> () -> (){
    func inner() {
        print("inner Function")
    }
    return inner
}

let result = outer()
result()

 

 

outer 함수 외부에서도 사용할 수 있습니다.

 

 

 

 


 

 

 

 

 

이렇게 Swift 함수 포스팅이 마무리되었습니다.

 

잘못된 내용이나 피드백이 있다면 언제든 환영합니다.
응원 댓글은 큰 힘이 됩니다 💪🏻