일급객체로서의 함수

  • 일급객체란? 함수가 다음의 조건을 만족하는 경우 일급 함수라 부른다.
  • 객체가 런타임 중에도 생성이 가능하다.
  • 매개변수나 반환값으로 함수를 전달할 수 있다.
  • 변수나 데이터 구조 안에 저장할 수 있다.
  • 이름과 관계없이 고유한 식별이 가능하다.

변수나 상수에 대입할 수 있다는 것

  • 함수를 통해 나온 값을 변수에 저장하는 것이 아닌, 함수 자체를 변수에 저장하는 것
  • 이렇게 저장한 변수 또는 상수는 함수처럼 사용이 가능하다.
  • 대입하는 과정에서는 아무런 실행도 일어나지 않는다.
  • 함수를 할당받은 변수 혹은 상수에 값을 넣어 실행해야 비로소 함수도 실행된다.
  • 함수가 할당된 변수 혹은 상수는 타입이 함수의 매개변수, 리턴값으로 정의된다.
func plus(inputNum: Int) -> String {
    return "결과값은 \(inputNum + 1) 입니다."
}

//함수타입으로 정의
//plusVar: (Int) -> String
var plusVar = plus //할당만으로는 아무런 실행도 일어나지 않는다.

plus(inputNum: 10) //결과값은 11 입니다.

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

  • 함수 자체를 반환할 수 있다.
func desc() -> String {
    return "이 함수는 desc입니다"
}

//desc2 함수는 () -> String 타입의 함수를 반환하는 함수다.
func desc2() -> () -> String {
    return desc
}

let test = desc2()
print(test()) //이 함수는 desc입니다

함수를 인자값으로 사용할 수 있다는 것

  • 함수의 타입을 통해 인자값으로 받을 함수를 설정할 수 있다.
  • 이때 함수를 받는 함수는 매개변수를 통해 들어오는 함수가 어떤 역할을 하는지 전혀 상관이 없다.(어떤 역할을 하는지 알 수 없기 때문에)
  • 실제 연산은 매개변수를 통해 들어오는 함수가 담당하고, 이때 중개역할을 하는 함수는 브로커라 부른다.
func success() -> String {
    return "성공!"
}

func fail() -> String {
    return "실패..."
}

func result(inputValue: String, successFN: () -> String, failFN: ()-> String) -> String {
    if Int(inputValue) != nil {
        defer {
            print("\(inputValue)")
        }
        return successFN()
    } else {
        defer {
            print("\(inputValue)")
        }
        return failFN()
    }
}

print(result(inputValue: "10", successFN: success, failFN: fail)) //성공!
  • 위에서 result 함수는 브로커이다.
  • 이처럼 함수를 쪼개어 만들게 되면, 브로커 함수의 내부 구조와 상관없이 브로커 함수 바깥에서 내부함수의 실행 과정을 간섭할 수 있다.
  • 결국 함수의 재사용성이 좋아진다.
  • defer 블록은 함수 또는 메소드에서 연산을 처리하는 과정에서 영향을 끼치지 않으면 함수 또는 메소드가 종료되기 직전에 호출된다.
  • defer 블록은 작성된 순서와 상관없이 항상 종료되기 직전에 실행된다.
  • defer 블록은 중첩하여 사용할 수 있다. 이 때에는 안쪽 블록이 가장 마지막에 실행된다.
  • 단순히 여러번 사용된 경우 마지막에 생성된 블록부터 실행된다.