티스토리 뷰

swift/문법

08. Swift 문법 - Functions

DevBee 2020. 10. 17. 14:47

지금부터 Swift 의 함수(Functions)에 대해 알아보겠습니다.

 

1. Functions

함수(Functions)은 특정 기능을 수행하는 코드 조각을 의미합니다. 함수를 사용하면 재사용(Reusability)이 가능하여 불필요한 반복을 피할 수 있고 수정도 간편해지는 장점이 있습니다. 스위프트에는 Swift Standard Libray 가 내장되어 있어 다양한 기본 함수를 가져다 사용할 수 있습니다.

 

함수는 다음과 같이 구분할 수 있습니다.

- Calling Functions: 함수를 가져와서 쓰는 것으로 함수 호출이라고 함
- Defining Functions: 직접 함수를 만들어서 사용하는 것으로 함수 선언, 함수 구현이라고 함

 

기본적인 함수 형태와 예는 다음과 같습니다.

// Calling Functions - 함수 호출
// functionName(parameters)

print("hello, Swift")

// Defining Functions - 함수 선언
// func name(parameters) -> ReturnType {
//     statements
// }
func sayHello() {
    print("Hello")
}
sayHello()

 

2. Return Values

함수를 실행한 결과를 함수가 호출된 부분으로 전달(return)하는데 이를 값을 리턴한다고 합니다. 함수의 반환 값을 지정하는 것은 다음과 같습니다.

func name(parameters) -> ReturnType {
    statements
    return expression
}

 

함수 리턴의 역할은 다음과 같습니다.

- 함수의 실행을 중지

- 함수의 리턴형이 선언되어 있다면, 리턴 키워드 다음에 오는 표현식을 평가 후 그 결과를 리턴

func add() -> Int {
    return 1 + 2
}
let r = add()
print(r)  // 결과: 3

if add() == 3 {
    print("three")  // 결과: three
}

func doSomething() {
    let rnd = Int.random(in: 1...100)
    
    if rnd % 2 == 1 {
        return
    }
    
    print(rnd)
}
doSomething()

// doSomething() 의 결과
// 랜덤으로 추출한 수가
// 홀수인 경우 return 되어 함수가 바로 종료되고
// 짝수인 경우에는 그 수를 출력합니다.

 

3. Parameters

함수에 값을 전달할 수 있는데 이때 이 값을 파라미터라고 합니다. 파라미터의 형태는 아래와 같습니다.

func name(name: Type, name: Type) -> ReturnType {
    statements
}

파라미터는 함수 바디에서 사용할 수 있는 임시 상수입니다.

func add(a: Int, b: Int) -> Int {
    return a + b
}
// 함수 호출 방법
// functionName(paramName: expr)

add(a: 1, b: 2)  // 결과: 3

// Default Value 지정하기
// (name: Type = Value)
func sayHi(to: String = "Stranger") {
    print("Hi, \(to)")
}
sayHi(to: "Swift")  // 결과: Hi, Swift
sayHi()             // 결과: Hi, Stranger

 

파라미터의 scope 는 함수 body 로 제한되므로 함수 내부에서만 사용 가능합니다. 파라미터는 함수 호출 시 생성되었다가 함수 종료 시 자동으로 삭제됩니다.

 

4. Argument Label

함수 선언 시 파라미터는 Formal Parameter, 함수 호출 시 파라미터는 Actual Parameter / Argument 라고 합니다. 이때, 호출 식에 있는 파라미터 이름을 Argument Label 이라고 합니다.

 

함수 선언 시 (name: Type) 으로 파라미터를 지정하는 경우에는 ParameterName = ArgumentLabel 이고,

(label name: Type) 으로 파라미터를 지정하는 경우 ParameterName 은 name, ArgumentLabel 은 label 이 됩니다.

 

Argument Label 은 함수 이름의 가독성을 높이기 위해 사용합니다.

함수 선언 시 함수 이름은 동사 + Argument Label 은 전치사 + Parameter Name 은 명사 형태로 만드는 것이 좋습니다.

 

정리하면, Parameter Name 은 함수 body 에서 함수로 전달된 값에 접근할 때 사용하고 Argument Label 은 함수를 호출하면서 argument 를 전달할 때 사용합니다.

func sayHello(to name: String) {
    print("Hello, \(name)")
    // Argument Label 은 함수 호출을 위해 사용되므로
    // 함수 body 에서는 사용이 불가
}
sayHello(to: "Swift")

// Argument Label 은 생략 가능하며 선언 시 생략했다면 호출 시에도 생략
// Parameter Name 은 생략 불가
func sayHello(_ name: String) {
    print("Hello, \(name)")
}
sayHello("Swift")

 

5. Variadic Parameters

가변 파라미터라고 하며, 하나의 Parameter 로 하나 이상의 Argument 를 전달하는 것을 말합니다. Argument 전달 시 배열 형태로 전달하게 됩니다. 형태는 다음과 같습니다.

// 선언 시 형태: (name: Type...)

print("Hello")           // 결과: Hello 
print("Hello", "Swift")  // 결과: Hello Swift

// 이때 nums 는 [] 형태로 값을 받음
func printSum(of nums: Int...) {
    var sum = 0
    for num in nums {
        sum += num
    }
    print(sum)
}
printSum(of: 1, 2, 3)        // 결과: 6
printSum(of: 1, 2, 3, 4, 5)  // 결과: 15

 

가변 파라미터는 다음과 같은 제약 사항을 가지고 있습니다.
- 개별 함수마다 가변 파라미터는 하나씩만 선언이 가능
- 선언 순서는 상관 없음
- 가변 파라미터는 기본값을 지정할 수 없음

 

6. In-Out Parameters

파라미터는 함수 외부로부터 전달된 값을 내부에서 사용하기 위한 임시 상수로 함수 내부에서 변경이 불가능하지만 Argument 로 전달된 상수의 값을 직접 변경할 수 있도록 한 것이 In-Out Parameters 입니다.

// 선언 시 (name: inout Type)
// 호출 시 functionName(argLabel: &expr)

var num1 = 12
var num2 = 34

func swapNumber(_ a: inout Int, with b: inout Int) {
    let tmp = a
    a = b
    b = tmp
}
num1  // 결과: 12
num2  // 결과: 34

swapNumber(&num1, with: &num2)

num1  // 결과: 34
num2  // 결과: 12

 

- Copy-In: Argument 로 전달된 값이 Parameter 로 복사되어 전달

- Copy-Out: 변경된 Parameter 의 값이 다시 Argument 로 복사되어 전달

 

In-Out Parameters 를 사용할 때 자주 하는 실수는 다음과 같습니다.

- 동일한 변수를 두번 이상 전달하는 것은 불가능

- 상수를 inout argument 로 불가능 (Copy-Out 이 불가능하기 때문)

- 리터럴을 전달하는 것은 불가능 (리터럴은 메모리 공간도 없고 값을 저장할 수 없기 때문)

- 기본값 지정도 불가능

- 가변 파라미터는 입출력 파라미터로 사용 불가능

 

7. Function Notation

함수 표기법으로 함수를 지칭하는 방법입니다. 이를 알고 있으면 레퍼런스 문서, function type 을 잘 이해할 수 있습니다. 형태는 다음과 같습니다.


- functionName(label:)
- functionName(label:label:)
- functionName

 

8. Function types

함수의 자료형을 표현하는 방법을 말합니다.

 

함수는 First-class Citizen 이고 특징은
- 변수나 상수에 저장할 수 있다.
- 파라미터로 전달할 수 있다.
- 함수에서 리턴할 수 있다.

// 함수 타입의 형태
// (ParameterTypes) -> ReturnType

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

let f1 = sayHello  // f1 의 타입은 () -> (), () = void 로 값이 없음을 의미
f1()

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

let f2: (String) -> () = printHello(with:)
f2("Swift")  // 상수에 저장된 함수 호출 시 Argument Label 쓰지 않음
func add(a: Int, b: Int) -> Int {
    return a + b
}

var f3: (Int, Int) -> Int = add(a:b:)
f3(3,4)

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

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

let f4 = swapNumbers(_:_:)
f4

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

let f5 = sum(of:)
f5
func add (_ a: Int, _ b: Int) -> Int {
    return a + b
}

func substract (_ 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
}

// 함수를 리턴하는 함수
typealias ArithmeticFunction = (Int, Int) -> Int

func selectFunction(from op:String) -> ((Int, Int) -> Int)? {
    switch op {
    case "+":
        return add(_:_:)
    case "-":
        return substract(_:_:)
    case "*":
        return multiply(_:_:)
    case "/":
        return divide(_:_:)
    default:
        return nil
    }
}

// 위와 동일
//func selectFunction(from op:String) -> ArithmeticFunction? {
//
//}

let af = selectFunction(from: "+") // add 함수가 반환되고 af 에 저장됨
af?(1, 2)                          // af = add 함수이므로 결과는 3

selectFunction(from: "*")?(12, 34)
// multiply 함수가 반환되고 그 함수에 12, 34 가 전달되므로 결과는 408

9.Nested Functions

다른 함수에 포함되어 있는 함수를 말합니다.

func outer() {
    func inner() {
        print("inner")
    }
    
    inner()
    
    print("outer")
}

outer()

// 결과
// inner
// outer


// global scope 에서는 inner 함수를 직접 호출할 수 없음
// inner 함수는 outer 함수 내부에서만 호출이 가능 (scope 축소)

func outer2() -> () -> () {
    func inner() {
        print("inner")
    }
    
    print("outer")
    
    return inner
}

let f = outer2()
f()

// 결과
// outer
// inner

지금까지 Swift  함수에 대해서 알아보았습니다.

'swift > 문법' 카테고리의 다른 글

10. Swift 문법 - Tuples  (0) 2020.10.17
09. Swift 함수 - Closures  (0) 2020.10.17
07. Swift 문법 - Optionals  (0) 2020.10.13
06. Swift 문법 - Control Transfer Statements, Labeled Statements  (0) 2020.10.12
05. Swift 문법 - Loop Statements  (0) 2020.10.11
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
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
글 보관함