본문 바로가기
공부/스위프트

[스위프트] 함수(파트3)

by 초코팅촉 2023. 7. 10.
728x90

파트 3에서 설명할 것은 좀 어렵다.
스위프트는 함수형 언어이다.
이를 설명하기 위해 우선 일급 객체에 대해서 알아보자.

일급 객체

객체가 다음의 조건을 만족하면 해당 객체를 일급 객체로 간주한다.

  1. 객체가 런타임에도 생성이 가능해야 한다.
  2. 인자값으로 객체를 전달할 수 있어야 한다.
  3. 반환값으로 객체를 사용할 수 있어야 한다.
  4. 변수나 데이터 구조 안에 저장할 수 있어야 한다.
  5. 할당에 사용된 이름과 관계없이 고유한 구별이 가능해야 한다.

일단은 함수도 객체이므로 위의 조건들을 함수가 만족할 경우 일급함수(First-Class Function라고 한다.
또한 해당 언어는 함수형 언어로 분류된다.
그래서 스위프트가 함수형 언어인 것이다.

이제부터 일급함수의 특성을 알아보자.

일급함수의 특성 (1) - 변수나 상수에 함수를 대입할 수 있다.

변수나 상수에 함수를 대입할 수 있다는게 별건가 싶을 수 있다.
정확히 말하자면 변수나 상수에 함수의 결과값을 대입하는게 아니라 함수 그 자체를 대입할 수 있는 것이다.
이렇게 하면 인자값을 입력받을 수 도 있고 반환값이 생길 수 도 있다.
이때 함수를 할당했기 때문에 해당 변수(상수)의 타입은 함수타입이다.

//함수선언
func sumNum(a: Int, b: Int) -> Int {
    print("함수 실행됨.")
    return a + b
}

//변수나 상수에 함수의 결과를 대입
var result = sumNum(a: 1, b: 2)    // "함수 실행됨."만 출력된다.

//우리가 볼건 위가 아니라 변수나 상수에 함수 자체를 대입하는 것
var fn1 = sumNum    // 아직 함수 실행 안됨.
var fn1 = sumNum(a:b:)    // 윗줄과 같은 표현.

fn1(1, 2)    // "함수 실행됨."이 출력됨. 위에선 함수를 할당만 해서
                // 실행안되고 실제로 밑에서 실행한 것이 된다.

//함수타입 설명 : 10번째 줄을 정석적으로 할당하려면
//                원래 함수의 매개변수 타입 및 반환타입을 전부 써야한다.(타입 어노테이션을 한다.)
var fn1: (Int, Int) -> Int = sumNum    // 이걸 줄이면 10번째 줄이 되는 것.

/*
*    만약  함수의 이름이 같으나 타입 어노테이션(매개변수의 타입이나 리턴타입)이 다르면
*    해당 어노테이션을 쓰면 이름이 같아도 상관없다.
*    그러나 만약 타입 어노테이션이 완벽하게 일치할 경우엔 문제가 생긴다.
*/

타입 어노테이션이 완전히 같으면 매개변수명만 다른 경우다.
이럴땐 12번째 줄처럼 매개변수명을 같이 써줘서 구별한다.

//예시
var fn1 = sumNum(a:b:)
var fn1 = sumNum(first:second:)

일급함수의 특성 (2) - 함수의 반환 타입으로 함수를 사용할 수 있다.

말그대로 위에서처럼 하는데 그걸 함수에 적용시키는 방법이다.

func aaa() -> Int {
    return 1
}

func temp () -> () -> Int {
    return aaa
}

var abc = temp()
abc()    // 1 반환됨.

뭔가 어려워 보이지만 쉽다. 함수 temp가 반환하는게 aaa함수라
aaa함수의 매개변수 타입 및 반환형을 묶어서 그대로 temp함수의 반환형에 써준다.

일급함수의 특성 (3) - 함수의 인자값으로 함수를 사용할 수 있다.

위의 2번과 반대되는 특성인데 a함수와 b함수가 있다고 할 때,
a함수 자체를 b함수에서 인자값으로 받으면 b함수 내부에서 a함수를 실행하고 다시 b함수로 넘어오게 된다.
함수를 인자값으로 넘겨주게 될때 해당 함수는 그 자체로 타입이 되므로 함수 타입이 된다.

func plusOne(num: Int) -> Int {
    return num + 1
}

func twoTimes(num: Int) -> Int {
    return num * 2
}

func tempFunc(number: Int, fn: (Int) -> Int) -> Int {
    return fn(number)
}

tempFunc(number: 4, fn: plusOne)    // 5

tempFunc(number: 2, fn: twoTimes)    // 4

4번째 줄을 보면 두번째 인자 fn의 타입이 plusOne, twoTimes 둘과 같은 형식으로 보인다.
이렇듯 형식만 일치하면 마지막 줄처럼 어떤 함수를 넣어도 함수 자체를 인자로 넘겨줄 수 있다.


스위프트 문법 - 함수, swift