티스토리 뷰

Swift

Swift [Functions]

이도형 2023. 2. 8. 04:12

Index

1.  Swift의 함수(Functions)

2. parameter와 argument

3. 함수의 오버로딩(overloading) 및 함수타입(Function Types)

4. 마무리

 

 

1. Swift의 함수(Functions)

Swift에서 함수의 가장 기본적인 형태를 설명한다. 간단한 설명과 예시 코드만 작성하고 넘어간다.

함수는 크게 4종류로 나뉜다.

1. input O, output O : input과 output 둘다 있는 함수

2. input O, output X: input만 있는 함수

3. input X, output O: output만 있는 함수

4. input X, output X: 둘다 없는 함수

 

1. input O, output O : input과 output 둘다 있는 함수

func twoNumAdd(a: Int, b: Int) -> Int { // Int타입의 input이 2개, Int타입의 output이 1개
    return a + b //return 키워드는 output이 있으므로 필수
}
twoNumAdd(a: 3, b: 5) // 8

2. input O, output X: input만 있는 함수

func introduce(name: String) { //String 타입의 input이 1개. output은 없다(return값도 당연히 없다)
    print("Hi, my name is \(name)") 
}
introduce(name: "이도형") // Hi, my name is 이도형

3. input X, output O: output만 있는 함수

func sayHelloString() -> String {
    return "Hello! "
}
print(sayHelloString() + "my name is 이도형") //이처럼 +로 문자열을 연결할 수도 있다
// Hello! my name is 이도형

4. input X, output X: 둘다 없는 함수

//아래 3개의 함수 모두 동일표현
func sayHello() {
    print("Hello, Swift")
}
func sayHello2() -> () {
    print("Hello, Swift")
}
func sayHello3() -> Void { //Void의 선언을 보면 ()와 동일함. typealias Void = ()
    print("Hello, Swift")
}

 

2. ⭐️parameter와 argument⭐️

2-1. parameter와 argument의 정의

parameter: 함수(func) 정의시 입력값으로 사용되는 변수

argument: 함수(func) 호출시 parameter타입(Int,String...)에 맞게 전달하는 값

(parameter는 '매개변수'나 '인자'라고도 통용되며 argument는 '인수'라고도 한글로 불리나 영어로 알고 있는게 헷갈리지 않는다. 다른 블로그나 문서를 참조할때도 영어가 대부분이었기에, 영어로만 표기해놓았다.)

//코드로 직관적 이해
func printName(name: String) {                  // name: String  (paremeter)
    print("나의 이름은 \(name) 입니다.")
}
printName(name: "이도형")          //   "이도형" (argument)

 

2-2 Argument Label(인자의 이름)

지금까지는 argument의 이름을 따로 설정하지 않고 argument를 그대로 썻다. 

 

사용 장점: 하지만 argument labelparameter앞에 명시함으로써, 그 함수가 무엇을 요구하는지 더 명확해진다.

(아래 코드를 보면 알겠지만, makyMyName을 치면 argument label이 자동 생성되어 편리하게 입력할 수 있다.)

 

2-3 ⭐️와일드 카드 패턴(언더바 _ )

: argument label의 생략이 가능하다. 

func addPrintFunction(_ firstNum: Int,_ secondNum: Int) {
    print(firstNum)
}
addPrintFunction(1, 2) // 3


2-4 ⭐️⭐️  Variadic Parameters(가변 파라미터)

 

기본 문법: 데이터타입...

사용 이점: 함수의 파라미터에 정해지지 않은, 여러개의 값을 넣는것도 가능하다

1.하나의 파라미터자리2개이상의 argument를 전달가능함(물론0개, 1개도 전달가능하다. 수의 제한이 없다는 뜻)

2.argument는 배열형태로 전달됨(배열생성의 번거로움을 줄여준다. 만약 함수내부에서 for문 구현시 편하게 사용가능)

3.가변파라미터는 개별함수마다 only 1개씩만 선언가능(선언순서는 상관없음)

4.가변파라미터는 기본값을 가질 수 없다.

func scoreAverage(scores: Double...) -> Double {
    var total = 0.0
    for n in scores { //for문. 배열 형태 전달의 이점
        total += n
    }
    return total / Double(scores.count) //scores.count는 배열 요소의 수를 나타낸다
}
scoreAverage(scores: 87.5, 92.5, 100, 100) //95

//와일드 카드패턴(언더바 _)과 함께 사용 가능
func scoreAverage(_ scores: Double...) -> Double {
    var total = 0.0
    for n in scores { //배열형태전달의 이점
        total += n
    }
    return total / Double(scores.count) //scores.count는 배열 요소의 수를 나타낸다
}
scoreAverage(87.5, 92.5, 100, 100) //95

//위아래 함수의 이름은 동일하고 각각의 함수로 실행도 가능. => 오버로딩(overloading) 되었기 때문. 아래서 설명

 

2-5 Default Parameter Values(함수 parameter에 기본값 부여하기)

func numFunction(num1: Int, num2: Int = 5) -> Int {
    return num1 + num2
}
numFunction(num1: 2) // 7
numFunction(num1: 2,num2: 8) // 10

 

2-6  inout 키워드

사용이유: 함수 내에서 함수에 전달된 변수 값을 바꾸기 위함(실제 원본값이 전달되기 때문이다)

기본문법: parameter 선언시, parameter 앞에 inout 키워드를 붙이고, 2. 함수사용시, argument앞에는 &를 붙인다.

inout 키워드 사용시 주의점은 3가지

 

1. 실제 원본값을 바꾸는 것이기에 당연히 상수가 아닌 변수(var)값을 argument(인자)로 전달해야한다.

2. inout 키워드는 가변파라미터와 함께 쓰일 수 없다. ex) func addNum(numbers: inout Int...) 틀린표현

3. inout parameter는 기본값을 가질 수 없다. ex) func addNum(a: inout Int = 20) 틀린표현

//공식문서 예제 swap함수
var num1 = 123
var num2 = 456
func swap(a: inout Int, b: inout Int) {
    var temp = a
    a = b
    b = temp
}
swap(a: &num1, b: &num2)
print("num1: \(num1), num2: \(num2)") // num1: 456, num2: 123

 

 

3. 함수의 오버로딩(overloading)과 함수타입(Function Types)

3-1 ⭐️오버로딩(overloading)⭐️

같은 이름의 함수에 파라미터를 다르게 선언하여, 하나의 함수 이름에 실제 여러 개의 함수를 대응 시키는 것

장점: 같은 기능을 제공하는 함수를 파라미터 타입마다 다른이름으로 구현하는건 번거로운일.

아래 함수는 value라는 이름 하나로도 4개의 동일기능 함수 정의 O

func doSomething(value: Int) { print(value) }
func doSomething(value: Double) { print(value) }
func doSomething(value: String) { print(value) }
func doSomething(_ value: String) { print(value) } //위에서 봤듯이 와일드 카드 패턴도 오버로딩인걸 알수있음.

doSomething(value: 5) //5
doSomething(value: 3.4) //3.4
doSomething(value: "Hi") //Hi
doSomething("Hello") //Hello

 

3. ⭐️⭐️⭐️3-2 함수타입(Function Types)

Swift의 개념을 한번 쭉 훑어본 결과ㅡ 앞으로 있을 것들을 배우는 데 있어서 가장 중요하다고 생각하는 개념이다. 설명에 들어가기전에 함수타입은 Why 필요할까?

간단히 말하면 Swift는 객체지향 언어이기도 하나 동시에 함수형 언어인 만큼, 함수를 1급객체 취급한다. 

=> 함수가 3가지 조건을 충족함을 뜻함.

1. 함수 역시 변수나 상수에 대입이 가능해야 한다.

1-1 함수가 하나의 타입으로 인식되어야한다.(Type Annotation이 가능해야함)

1-2 함수의 이름만으로 대입이 가능해야한다.

2. 함수의 parameter로 함수를 전달할 수 있어야 한다.

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

(위 3가지를 한번에 이해하기는 버거운게 사실이다. 하지만 1번의 개념만 이해한다면 2,3번은 충분히 쉽게 이해해볼만하다. 하지만 이렇게 강조하는 이유는

⭐️함수타입은 뒤에 있을 클로저(Closure)를 배울때 너무 중요한 개념이다. 함수타입이란 개념에 익숙해지고 잘 다룰 줄 알게 된다면 차후에 포스팅할 클로저(Closure)를 이해하는 데 큰 도움이 된다.)

3조건에 대해 이해하기 위해서는 먼저 아래코드의 물음에 답할 수 있어야 한다. 

 

addTwoInts와 multiplyTwoInts 함수의 타입은 동일하다. 이를 기호 또는 한문장으로 풀어 표현한다면?

//공식문서 예제
func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

Answer: 

글로 표현한다면 두 함수는 모두 Int 타입인 2개의 파라미터를 가지며, 1개 Int타입을 반환한다.

기호로 표현한다면 (Int,Int) -> Int

 

위 코드와 답안이 이해가 되었다면 앞에서 말한 함수타입(조건1과 조건2)을 이해할 준비가 되었다.

//공식문서 예제

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}
//1. 함수 역시 변수나 상수에 대입이 가능해야한다
var mathFunction: (Int, Int) -> Int // 1-1. type Annotation로 함수 타입 명시 => 함수도 하나의 타입이다!
print(type(of: mathFunction))  //(Int, Int) -> Int

mathFunction = addTwoInts // 1-2. 함수의 이름을 변수에 대입
mathFunction(5,10) // 5 + 10 = 15 //변수가 함수를 가리키게되어 실행함
//여기서 변수 mathFunction와 addTwoInts의 타입은 동일한 걸 확인할 수 있고
// 타입이 같기에, 함수를 변수에 할당하는게 가능하다는 것도 알게 되었다. multiplyTowInts역시 동일한 타입이기에 할당이 가능하다.
mathFunction = multiplyTwoInts

mathFunction(5,10) // 5 * 10 = 50

//2. 함수의 parameter로 함수를 전달할 수 있다
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 5, 10) // Result: 15
printMathResult(multiplyTwoInts, 5, 10) //Result: 50

//3. 함수의 return타입으로 함수를 사용할 수 있다.

func out() -> ( () -> () ) { //1번째 ()는 out함수의 parameter를 의미,
// 2번째 ( () -> () )는 out함수의 return타입도 맞지만, inn함수의 타입이기도함.
// 아래의 type(of:inn) 참조

    func inn() {
        print("@@")
    }
    
   //print(type(of: inn)) //inner 함수의 타입: () -> ()
    
    return inn
}

let c = out()
c() // @@ //out함수 내부의 inn함수가 실행

 

4. 마무리

 Swift의 함수를 처음 공부할때, 여러 용어가 나와서 머리가 복잡했던 기억이 있다. 그래서 키워드를 중심적으로 정리하고자 했다. 다소 꼼꼼한 감이 없진 않지만, 이 한 포스팅으로 swift 함수의 상당부분을 담을 수 있어서 다행이다.

 함수의 1. 간단한 형태(4가지)를 시작으로, parameter와 argument, Argument Label,  와일드 카드 패턴, Variadic Parameters(가변 파라미터),  Default Parameter Values(함수 parameter에 기본값 부여하기),  inout 키워드, 함수의 오버로딩(overloading)과 함수타입(Function Types)에 대해 살펴보았다.

각 인덱스 별로 기억에 남아야 될 것은

1. 함수의 형태(input과 output)

2-1.  parameter와 argument를 헷갈리지 않는 것

2-2. argument label 사용의 이점

2 -3. 와일드카드 패턴의 방식( _ )

2-4. 가변 파라미터의 사용방법(간단코드 구현). 이점

2-5 파라미터에 기본값 부여하는 방법(간단 코드 구현)

2-6 inout 키워드를 언제 사용하는지

3-1 함수의 오버로딩이란 개념과 장점

3-2 ⭐️함수타입이 무엇이고, 어떤 조건을 충족하는지 안다면. (이는 클로저를 공부하며 함수와 비교하면서 더 자세히 보완될 개념) PASS

 

 

Inflearn Allen님의 강의 노트

Swift 공식문서

반응형

'Swift' 카테고리의 다른 글

Swift [Collection Types]  (0) 2023.02.10
Swift [옵셔널(Optionals) 총정리]  (0) 2023.02.09
Swift [Tuples/Loops]  (0) 2023.02.07
Swift [연산자(Operators)와 조건문(if문/switch문)]  (0) 2023.02.05
Swift [Variables/Constants/Types]  (0) 2023.02.04
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함