함수도 일급시민이다 feat. Function Type

NOAH·2021년 8월 18일
0

SWIFT

목록 보기
1/7
post-thumbnail

일급시민의 큰 특징 3가지는 다음과 같다.

First - Citizen

  • 변수나 상수에 저장할 수 있다.
  • 파라미터에 저장할 수 있다.
  • 함수에서 리턴할 수 있다.

즉, 변수, 상수, 그리고 파라미터에 저장하고, 리턴도 할 수 있으려면
Int, Double, String 같은 '자료형'을 가지고 있어야 한다.
그렇다. 함수에도 자료형이 존재 한다.


func sayHello() {
	print("Say, Hello")
}

//let f1 = sayHello() // X
// 괄호는 제거하고 함수이름만 할당 
// 함수 자체가 저장된다. 
let f1 = sayHello
f1() // () -> ()

자료형이 있기 때문에 일급 시민(First Class Citizen)로써
변수나 상수에 저장할 수 있다.

이번 에는 파라미터가 존재하는 함수를 할당해보자.


func printHello(with name: String) {
	print("Hello, \(name)!!")
}

let f2: (String) -> () = printHello(with:) // (String) -> ()
let f3 = printHello(with:) // (String) -> ()

상수 f2는 직접 형식을 지정해주고 함수를 할당했고,
f3는 형식추론을 사용했지만 저장된 함수는 동일하다.


f2("friend")
// Hello, friend!!

원래 함수를 호출할 때는 Argument Label를 항상 사용했지만
상수에 저당된 함수를 호출 시에는 Argument Label를 쓰지 않는다.
(Function type 에는 파라미터와 리턴형에 대한 정보만 전달 되기 때문에)

func add(a: Int, b: Int) -> Int {
	return a + b 
}

var f4: (Int, Int) -> Int = add(a:b:)
f4(1,2) // Argument Label X

// 3

와일드 카드로 숨길 수도 있다.

func add(_ a: Int, with b: Int) -> Int {
	return a + b 
}

var f4 = add(_:with:)
f4() // Argument Label X

// 3

입출력 함수를 파라미터도 할당 가능하다.

func swapNumbers(_ a: inout Int, _ b: inout Int) {
}

let f5 = swapNumbers(_:_:) // (inout Int, inout Int) -> ()

가변 매개변수를 가지는 경우

func sum(of numbers: Int...) {
}

let f6 = sum(of:) // (Int...) -> ()

사칙연산을 코드 구현해보자.


func add(_ a: Int, _ b: Int) -> Int {
	return a + b 
}

func subtract(_ a: Int, _ b: Int) -> Int {
	return a - b 
}

func multiply(_ a: Int, _ b: Int) -> Int {
	return a * b 
}

func divide(_ a: Int, _ b: Int) -> Int {
	return a / b 
}

4개의 연산하는 함수도 일급시민라는 것을 알면,
호출하고 싶을 때 자료형만 적합하다면
사용자가 원하는 함수를 파라미터에 저장하고 리턴할 수 있다.

함수를 리턴하는 함수를 사용하자.

func selectFunction(from op: String) -> (Int, Int) -> Int {
}

이렇게 정의해주어도 컴퓨터 입장에서는 무리가 없다.
(Int, Int) -> Int 또한 하나의 자료형이기 때문이다.
하지만 함수를 사용하는 사람 입장에서는 당황할 수 있다.

typealias ArithmaticFunction = (Int, Int) -> Int
func selectFunction(from op: String) -> AritmaticFunction? {

switch op {
	case "+" :
	return func add(_:_:)
	case "-":
	return func subtracj(_:_:)
	case "*":
	return func multiply(_:_:)
   	case "-":
   	return func divide(_:_:)
        default : 
        return nil
       }

}

typealias를 통해 자료형을 미리 지정해놓은다면 함수를 리턴하는 함수라는 것을 쉽게 알 수 있다.
(디폴트의 리턴값은 nil을 전달해주어서 리턴탕입을 옵셔널로 선언했다.)

let af = selectFunction(from: "+")
af?(1,2)
// 3 

혹은 이렇게도 가능하다.

selectFunction(from: "*")?(1,2)
// 3

0개의 댓글