본문 바로가기
iOS/Swift

[iOS/Swift] 1등 시민, 1급 객체함수 (First Class Citizen)

by iosdevlime 2023. 1. 18.

드디어, 함수 마지막 파트까지 도달했네요!

 

앞서 다룬 함수관련 포스팅의 내용 중...

  • 함수의 표기법 (Function Notation) : 함수를 '명명'하는 일종의 규칙
  • 함수의 타입(Function Type) : 함수 또한 일종의 '복합타입' 

 

위 2가지 매우 간단한 개념은

이번 포스팅에서 배울 1급 객체함수에서 활용됩니다.

 

 

 


 

 

 

Swift의 프로그래밍 패러다임과 1급 객체

Swift는, 함수형 프로그래밍 지향 패러다임에 따라 1급 객체로서의 조건을 갖춘다

 

'1급 객체' 란 생소한 개념은,

Swift란 프로그래밍 언어의 패러다임에서 시작됩니다.

 

현재 다루고 있는 Swift란 언어는

'객체지향 언어'이자, '함수형 프로그래밍' 패러다임을 지향하는 언어입니다.

 

(CS 파트에서 객체지향 및 함수형 프로그래밍에 대해 보다 구체적으로 다루도록 하겠습니다) 

 

 

 

함수의 특징과 1급객체의 조건

  • Swift의 언어 패러다임에 따라, 함수는 하나의 객체(Object)입니다.
    • 각각의 함수(객체)는 서로 주고-받으며 자료를 처리할 수 있습니다.
    • 그렇기 때문에, 함수는 '1급 시민(First-Citizen)'의 조건을 충족합니다.

 

  • 함수가 1급 시민, 즉 1급 객체가 되기 위해선 3가지 조건이 있습니다.
    • 변수 또는 상수에 함수를 할당할 수 있어야 한다. (Binding)
    • 함수의 반환값(Return)으로 함수(객체)를 사용할 수 있어야 한다.
    • 함수의 매개변수(Parameters)로 함수(객체)를 전달할 수 있어야 한다. (Callback)

 

 

Swift의 함수는,

위 3가지 조건을 모두 만족합니다.

 

 

 


 

 

1급 객체함수의 3가지 조건

값으로서 ①저장되고, ②반환값③파라미터로 활용!

 

Swift에서의 함수가,

 

어떻게 '1급 객체'로서 활용 가능하고, 작성될 수 있는지..

1급 객체가 되기 위한 3가지 조건에 따른 예시를 통해 구체적으로 살펴보도록 하겠습니다.

 

 

 

첫 번째, 변수 또는 상수에 할당할 수 있어야 한다 (Binding)

  • 함수 자체를 변수 또는 상수에 대입(할당)하게 되면?
    • 해당 변수와 상수는 함수 그 자체로서 활용되게 됩니다!
    • 함수의 이름변수와 상수에 대입(할당)함수의 기능 부여
// 파라미터로 추가되는 값에서 1씩 빼는 함수를 만들고,
func countDidMinus(count: Int) -> Int {
    return count - 1
}

// minus란 상수에 함수 countDidMinus를 할당함!
let minus = countDidMinus

// 해당 상수를 호출하고, 처리값으로 4을 대입하면?
// 정상적으로 함수의 기능이 작동한다!
minus(4) // 3

 

 

  • 만약, 같은 이름의 함수(Overloading)를 변수 또는 상수에 대입(할당)하게 된다면..
    • 반드시, 해당 변수와 상수의 타입을 명시(Type Annotations)해야 합니다!
    • 여기서 타입은, 앞선 포스팅에서 학습한 '함수 타입' 입니다.
// 아래와 같이 동일한 이름의 함수(오버로딩)가 있을 경우
func coundDidPlus(_ count: Int) { }
func coundDidPlus(_ count: Int, _ label: String) { }


let plus = coundDidPlus // 컴파일러 Error 발생!

// 따라서, 함수의 타입을 작성해줌으로서 구분해야 함
// 첫 번째 함수를 할당하고자 한다면?

let plus1: (Int)-> () = coundDidPlus
// 정상적으로 할당

 

 

  • 또한, 같은 이름과 같은 파라미터/리턴타입을 가지고 있는 함수가 있을 경우..
    • 여기선, 대입(할당)하는 함수에 표기법(Function Notation)을 명명 해야합니다. 
    • XCode에서 코드를 작성할 시, 자동으로 표기법을 완성시켜줍니다.
// 아래와 같이 동일한 이름의 함수(오버로딩)가 있고,
// 타입(파라미터 형태) 또한 동일하다면?
func countWillDivide(count: Int) { }
func countWillDivide(_ count: Int) { }

// 이와 같이, 함수의 표기법을 이용하여 대입(할당)한다.
// 첫 번째 함수를 할당하고자 한다면?

let divide1 = countWillDivide(count:)
// 정상적으로 할당

 


 

 

두 번째, 함수의 반환값(Return Value)으로 함수를 사용할 수 있어야 한다.

  • 함수의 반환값 (Return [ ...  ])으로서 함수를 사용한다? 
    • 말 그대로, 함수 그 자체의 기능반환할 수 있습니다.
    • 예시 코드를 먼저 살펴보자면, 다음과 같습니다. 
func outside () -> () -> () {
    func inside() {
        print("inside 함수가 반환되었습니다.")
    }
    
    return inside
}

let callInside = outside()

callInside() // "inside 함수가 반환되었습니다"

 

  • 함수를 반환하려면, 해당 함수의 반환 타입에 '함수타입'을 작성해야 합니다.   
    • 위 코드를 보면, 'outside'란 함수 내 'inside'란 함수를 반환값으로 활용합니다.
    • 그런데, outside 함수의 매개변수와 리턴타입의 모양이  ( ) -> ( ) -> ( )    ???

func outside (①parameters) -> (②parameters) -> (return type)

 outside 함수 
② outside 함수의 리턴타입 (즉, inside 함수의 타입)

 

 


 

 

세 번째, 함수의 매개변수(Parameters)로 함수를 사용할 수 있어야 한다.

  • 함수의 반환값으로 매개변수를 사용할 수 있었으니, 매개변수로도 가능하겠죠?
    • 이는 흔히 콜백(Callback) 함수라고 하며, 주로 클로저를 통해 작성합니다.
      (클로저는 다음 포스팅에서 구체적으로 다룰 예정입니다.) 
    • 예시 코드를 살펴보자면, 다음과 같습니다.
// 매개변수로 활용할 함수 messageA를 선언함
func messageA() {
    print("Hello, Lime")
}


// 콜백함수를 작성하고, 매개변수 타입을 함수타입으로 작성함
func messageB(_ callback: () -> ()) {
    callback() // 매개변수를 반환함!
    // ()을 붙여주는 이유는, 함수를 '실행'해야 하기 때문
}

messageB(messageA) // "Hello, Lime"

 

 


 

드디어 기본적인 함수 포스팅이 마무리 되었습니다 ! 

 

함수의 타입과 표기법은 활용 및 명명 방식이 다소 헷갈릴 수 있으므로

반드시 1급 객체함수와 함께 복습하시길 바랍니다.

 

 

다음 포스팅에서는,

 

함수와 동일한 개념이지만, '이름이 없는 함수' 

클로저(Closure)에 대해 살펴보겠습니다.

 

댓글