본문 바로가기

iOS/Swift

Swift) 함수(Function) 정복하기 (3/3) - 함수 표기법 / 함수 타입 / 일급 객체 함수

 

 

 

안녕하세요 :) 🐮🐮입니다 

이번 포스팅은 함수 정복하기란 포스팅을 끝내보려고 합니다 ^^;

내용ㅇ ㅣ좀 어려울 수도 있다 생..ㄱ..ㅏㄱ....

 

이전 포스팅을 천천히 다 읽고 오심을 추..천

모든 포스팅은 편의 말투로 합니다~!!

 

 

 

 

1. 함수 표기법

 

먼저 함수 표기법에 대해서 공부를 해보겠음

아니 그전에 함수 표기법이 뭔데 싶겠지만

말 그대로 함수를 표기하는 방법임!!

 

이 함수 표기법을 보통 어디서 볼 수 있냐면,

애플 문서 있잖음? Apple Documentation에 함수를 검색하다 보면

 

 

 

 

머 이런 식으로 함수들이 표기되어 있단 말임???

이것들이 바로 함수 표기법이란 것임!!!

 

또한 다음에 배우겠지만, 변수(상수)에 함수를 대입하기 위해선

함수 표기법으로 대입을 해야 정확히 대입할 수 있음!!!

 

따라서 우린 함수 표기법에 대해 알아야 함니다

 

자, 함수 표기법에선 오로지 ⭐️ 파라미터⭐️만 표현함!

리턴 타입은 있든 없든 함수 표기법엔 상관없음!!!!!!!!!!

 

 

 

1-1. 파라미터가 있는 함수 표기법

 

파라미터가 있을 경우,

 

 

 

 

이런 식으로 표현함!!!!

()괄호 안에 Argument Label을 써주고 옆에 :를 붙여줌

예로 보면,

 

 

func sayHello(name: String )   { }            // sayHello(name:)
func sayHello(_ name: String ) { }            // sayHello(_:)
func sayHello(to name: String) { }            // sayHello(to:)
 

 

 

만약 _(Wildcard Pattern)으로 Argument Label을 생략했다 하면,

ArgumentLabel 자리에 _를 써주어야 함!

파라미터가 여러 개라면 

 

 

func sayHello(name: String, age: Int) { }            // sayHello(name:age:)

 

 

요롷게!!! ㅎㅎ

혹시 Argument Label이 뭔지 모른다면 이 포스팅을 보고 오시오...

 

 

 

1-2. 파라미터가 없는 함수 표기법

 

자, 파라미터가 없을 경우엔

 

 

 

 

함수 이름만 덩그라니 쓰면 표기법 끝임!!!!

이또한 예로 본다면

 

 

func sayHello() { }                    // sayHello
func sayHelloToSodeul() { }            // sayHelloToSodeul

 

 

이렇게 표기함!! 근데 헷갈릴 수 있는 게 

 

sayHello()

sayHelloToSodeul()

 

이렇게 표기해야하는 거 아닌가여??할 수도 있지만,

()를 붙이는 것은 파라미터가 없는 함수를 호출하는 것임!!!!!!!  

 

따라서 파라미터가 없을 경우,

함수표기법에선 () 자체를 없애주어야 함!

 

 

 

 

2. 함수 타입

 

여러분 Swift에서 함수는 자료형을 갖고 있답니다?????

함수가 웬 자료형이냐 싶겠지만, 함수 또한 자료형을 가지고 있고

이를 함수 타입이라고 함!!

 

 

 

 

함수 타입은 위와 같이 표현하는데, 여기서 중요한 것은

우리가 함수를 선언할 때 Return Type이 없다면 생략하고 썼지만,

함수 타입에선 Parameter Type이건 Return Type이건 아무 것도 생략해선 안됨!!

 

이를 유념하며, 함수 타입을 표현하는 방법을 봅시다 :)

 

 

 

2-1. 파라미터가 없는 함수 타입

 

 

func sayHello() {}

 

 

자, 이런 함수의 경우 함수 타입이 어떻게 되는지 봅시다 :)

보는 방법은 Playgorund에서 함수 표기법을 써주시면,

 

 

 

 

이 함수의 타입은 () -> () 라는 것을 알 수 있음!

왜냐? 파라미터도 없고, 리턴타입도 없기 때문임!!!

(Swift에선 Void 대신 보통 ()로 나타냄)

 

 

 

2-2. 파라미터가 있는 함수 타입

 

 

func sayHello(_ name: String) {}

 

 

자, 이렇게 파라미터가 있을 경우엔 어떤 타입일지 보겠음.

마찬가지로 함수 표기법을 사용해서 보면,

 

 

 

 

 sayHello란 함수의 타입은 (String) -> () 인 것을 알 수 있음

 

자, 여기서 중요한 거!!!!!

함수 타입에선 Argument Label이건, Parameter Name이고 뭐고 다  필요 없음

단지, 해당 Parameter의 타입만 중요함!!!

 

따라서 만약 Parameter가 다음과 같이 여러 개라면,

아 이번엔 Return Type도 추가해보겠음

 

 

func sayHello(_ name: String, _ age: Int, alias: String) -> String {}

 

 

 

함수의 타입은 

 

 

 

 

(String, Int, String) -> String

이렇게 파라미터의 타입만 나열해둔 것임!!

Return 타입또한 위처럼 표시됨

 

 

+ 가변 파라미터의 경우 함수 타입은

 

 

 

 

++ 입출력 파라미터의 경우 함수 타입은

 

 

 

 

이런 식으로 표현 된답니다...... :D

 

 

 

 

3. 일급 객체 함수

 

여러분 Swift는 객체지향 언어인 동시에 함수형 언어

함수형 언어가 무엇이냐, 함수가 1급 객체로 취급 되어 개짱인 것임

 

그럼 도대체 일급 객체가 무엇인데 싶겠지? 호호

일급 객체의 조건은 뭐 객체가 런타임에도 생성되어야 하고,

파라미터로 객체를 전달할 수 있고, 반환값으로 객체를 사용할 수 있고 등등 있는데,

그중 함수가 일급 객체가 되기 위해선 다음과 같은 조건들을 만족해야함

 

 

 

3-1. 변수나 상수에 함수를 대입할 수 있어야 한다

 

일급 객체 함수가 되기 위해선,

변수나 상수에 함수를 대입할 수 있어야 하는데,

먼저, 대입한다는 개념은 함수를 실행해서 결과값을 대입한다는 것이 아님!

함수 자체변수나 상수에 대입해서,

해당 변수나 상수가 함수 자체처럼 쓰이는 것을 말함!

 

변수나 상수를 대입하는 방법이 총 3가지가 있음!!! 

 

 

 ① 함수 이름으로 대입하기 

 

 

func sayHello(_ name: String) {}

let f = sayHello

 

 

자, 이런 식으로 함수 이름으로 대입할 수도 있음!

(물론 Parameter, Return 값이 없는 함수 표기법 또한 이렇지만)

 

근데, 이렇게 함수 이름으로 대입할 경우 문제점이 무엇이냐면

sayHello라는 함수가 오버로딩된 경우

 

 

func sayHello(_ name: String) {}
func sayHello(_ name: String, _ age: Int) {}

let f = sayHello //error!

 

 

sayHello라는 이름의 함수가 두 개이기 때문에,

어떤 함수를 말하는 것이냐???는 컴파일에러가 뜸!

따라서 이럴 땐 다른 방법을 사용해야함

 

 

 ② 타입 어노테이션을 통해 함수 타입을 명시해주기 

 

 

func sayHello(_ name: String) {}
func sayHello(_ name: String, _ age: Int) {}

let f: (String) -> () = sayHello

 

 

위에서 배운 함수 타입을 이용해서

Type Annotation으로 명시해주는 것임!!!

 

근데, 함수 타입을 명시해주는 것또한 문제점이 있는데,

 

 

func sayHello(name: String) {}
func sayHello(_ name: String) {}

let f: (String) -> () = sayHello //error!

 

 

이렇게 파라미터 타입 & 리턴 타입이 동일한 함수가 존재할 경우

 함수 타입 또한 동일하기 때문에 컴파일러는 또 에러를 뱉음

따라서 이럴 땐 다음 방법을 사용해야 함

 

 

 ③ 함수 표기법을 통해 대입하기 

 

위에서 함수 표기법을 왜 배워야하는지에 대해 말할 때

잠깐 설명했었음

 

 

func sayHello(name: String) {}
func sayHello(_ name: String) {}

let f = sayHello(name:)

 

 

이렇게 sayHello의 함수 표기법을 이용해서 대입하면,

그땐 문제 해결 ~_~

 

( + Parameter Type, Return Type이 없는 함수가 오버로딩된 경우,

함수 표기법이 아닌 Type Annotation으로 타입을 명시해주어야 함)

 

 

 

.

.

자 함수 대입하는 방법에 대해선 다 배웠음!

근데 헷갈리면 안되는 것이 우린 f라는 상수에 함수를 대입한 것이지,

sayHello라는 실행 결과를 f에 대입한 것이 아님!

 

따라서, f라는 상수에 저장된 것은 sayHello라는 함수이기 때문에

f를 통해서 우리가 저장한 함수를 실행시킬 수 있고, 실행할 때는 다음과 같이 실행함

 

 

 

 

자, 또 중요한 것!

함수를 저장한 상수 f를 통해 함수를 호출할 땐 Argument Label을 사용하지 않음

왜냐? sayHello라는 함수 자체를 호출할 땐 당연히 Argument Label이 필요하지만,

sayHello를 f라는 상수에 넣는 순간 함수 타입만 가져가지Argument Label까지 가져가진 않음

 

만약, 함수를 저장한 상수(변수)를 호출할 때 Argument Label을 사용하면

 

 

 

 

에러 떠용 

 

 

 

3-2. 함수의 반환 타입으로 함수를 사용할 수 있다

 

 

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

 

 

위에서 보면 outer란 함수가 inner라는 함수를 반환하구 있음!!!!

참고로 리턴할 함수 표기는 함수 대입할 때와 똑같이

함수 이름을 쓰든, 표기법을 쓰든, Annotation을 쓰든 하면 됨!

 

자 근데 위 함수를 보면 어디서 띠용 하냐면,

 

() -> () -> ()

 

????

이부분이 이해가 안 갈거..

자...... 함수를 반환하려면,

 

"반환 타입"에 반환하려는 "함수 타입"을 작성

 

해야 한다는 사실을 알아두어야 함

따라서 위 표현식의 의미는

 

 

 

 

이렇게 이해하면 됨!!!!

첫 번째 괄호는 outer 함수의 파라미터고,

첫 번째 () -> 뒤에 오는 것은 리턴하고자 하는 함수(inner)의 타입임!!!

 

따라서, 만약 다음과 같이 

 

 

let f = outer()
f()

 

 

outer 함수의 리턴 값을 받아서 실행해보면,

 

 

 

 

inner가 실행이 됨 :)

 

 

 

3-3. 함수의 파라미터로 함수를 전달할 수 있다

 

자, 마지막임! 

보통 파라미터로 함수를 전달하는 것을 어디서 많이 사용하냐면,

 

콜백함수

 

에서 사용하는 것임!!!!

예를 들어, 데이터를 fetch 하는 함수를 실행했을 경우,

너 데이터 다 가져왔으면 이 함수 실행시켜줘!

하고, 함수를 파라미터로 전달해 주는 것임

 

따라서, 보통 클로저를 통해 작성하는데

함수 클로저, 둘 다 봐보겠음

 

 

func doSomething(_ callback: () -> ()) {
    callback()
}
 

 

 

자, 이렇게 함수를 파라미터로 받을 경우,

 

"파라미터의 타입"을 "함수 타입"으로 작성

 

해주어야 함!!!!

그럼, 두 가지로 파라미터에 함수를 넘겨줄 수 있는데

 

 

 ① 함수(Named Closure)로 넘겨주기 

 

 

func success() {
    print("Success!")
}
 
doSomething(success)

 

 

이렇게 함수 자체를 넘겨줄 수도 있고,

 

 

 ② 클로저(Unnamed Closure)로 넘겨주기 

 

 

doSomething {
    print("Success!")
}

 

 

이렇게 클로저를 통해 넘겨줄 수도 있음!

(클로저는 다다음쯤에 포스팅 할거임)

 

아, 참고로 함수를 파라미터로 받은 경우,

파라미터로 받은 함수를 "실행" 해야 하므로, 

 

 

func doSomething(_ callback: () -> ()) {
     callback()
     callback()
     callback()
}
 

 

 

()를 통해서 호출해주어야 함!

그럼 실제 내가 전달한 함수(클로저)가 doSomething 함수에 의해 3번 실행됨

 

 

 

 

파라미터가 있다면 다음과 같이!!

 

 

func doSomething(_ callback: (String-> ()) {
    callback("sodeul")
    callback("sodeul")
    callback("sodeul")
}
 
doSomething {message in
    print("Success!" + message)
}
 

 

 

사용하시면

 

 

 

 

됩니다 :)

 

 

 

 

 

.

.

.

음 내용이 좀 어려웠을 수도 있는데

이제 함수에 대해 기본적인 것은 다 아는 겁니다 :)

다음에 배울 클로저까지 다 이해한다면

Swift 함수 정복 ~~~~🌝🌝🌝

 

함수 표기법

함수 타입

 

이 둘을 헷갈리지 말고 꼭 제대로 공부 한다면,

막히는 내용은 없었을 거라 생각합니다 :)

 

잘못된 내용이나 피드백 환영 🌞🌞

 

 



Calendar
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
최근 댓글
Visits
Today
Yesterday