Swift/Swift 기본기

05. 함수 (Functions)

여성일 2023. 3. 18. 15:25
728x90
정의와 호출 (Defining and Calling Functions)

함수를 선언할 때는 가장 앞에 func 키워드를 붙히고 (person: String) 파라미터 형 그리고 -> String 형태로 반환형을 정의한다.

func 함수명(파라미터명: 파라미터타입) -> 반환타입 {
   실행 구문
   return 반환값
}
func helloFunc(param: String) -> String {
   let returnValue = "Hello, " + param + "!"
   return returnValue
}

✔️ 위의 예제와 같이 함수에 인자 값을 넣어 호출할 수 있다.

 

func helloFunc(param: String) -> String {
   //let returnValue = "Hello, " + param + "!"
   //return returnValue
   return "hello", + param + "!"
}
print(helloFunc(param: "seongil") 
// Hello, seongil!

✔️ 위의 예제와 같이 실행 구문을 반환하는 구문과 합쳐서 더 짧게 만들수 있다.

 

함수 파라미터와 반환 값 (Function Parameters and Return Values)

1️⃣ 파라미터가 없는 함수 (Functions Without Parameters)

func helloworldFunc() -> String {
   return "Hello, world"
}
print(helloworldFunc())
// Hello, world

2️⃣ 복수의 파라미터를 사용하는 함수 (Functions With Multiple Parameters)

func multipleFunc(value: Int, value2: Int) -> Int {
    let mul = value*value2
    return mul
}
multiple(value: 10, value2: 5) // 50

3️⃣ 반환 값이 없는 함수 (Fucntions Without Return Values)

func printName(name: String) {
   print("Hello, \(name)!")
}
printName(name: "seongil")
// Hello, seongil!

⚠️ 엄밀이 말하면 위 함수는 반환 값을 선언하지 않았지만 반환 값이 있다. 반환 값이 정의 되지 않은 함수는 void라는 특별한 타입을 반환한다. void는 간단히 ()를 사용한 빈 튜플이다.

 

4️⃣ 복수의 값을 반환하는 함수 (Functions with Multiple Return Values)

func minMax(array: [Int]) -> (min: Int, max: Int) {
   var minValue = array[0]
   var maxValue = array[0]
   for value in array[1..<array.count] {
      if value < minValue {
         minValue = value
      } else if value > maxValue {
         maxValue = value
      }
   }
   return (minValue, maxValue)
}
var numArr: [Int] = [1, 5, 2, 10, 7]
print(minMax(array: numArr))
// (min: 1, max: 10)

✔️ 위의 예제와 같이 튜플을 함수의 반환 값으로 사용할 수 있다.

 

func minMax(array: [Int]) -> (min: Int, max: Int) {
   var minValue = array[0]
   var maxValue = array[0]
   for value in array[1..<array.count] {
      if value < minValue {
         minValue = value
      } else if value > maxValue {
         maxValue = value
      }
   }
   return (minValue, maxValue)
}
var numArr: [Int] = [1, 5, 2, 10, 7]
let bound = minMax(array: numArr)
print("minValue = \(bound.min), maxValue = \(bound.max)")
// minValue = 1, maxValue = 10

✔️ 위의 예제와 같이 반환 값의 인자를 반환 값을 접근하는 접근자로 사용할 수 있다.

 

5️⃣ 옵셔널 튜플 반환형 (Optional Tuple Return Types)

func minMax(array: [Int]) -> (min: Int, max: Int)? {
   if array.isEmpty { return nil }
   var minValue = array[0]
   var maxValue = array[0]
   for value in array[1..<array.count] {
      if value < minValue {
         minValue = value
      } else if value > maxValue {
         maxValue = value
      }
   }
   return (minValue, maxValue)
}
var numArr: [Int] = [1, 5, 2, 10, 7]
let bound = minMax(array: numArr)
print("minValue = \(bound?.min), maxValue = \(bound?.max)")
// minValue = Optional(1), maxValue = Optional(10)

✔️ 위의 예제와 같이 함수에서 반환되는 튜플 타입이 "값이 없을" 가능성이 있는 경우 옵셔널 튜플 반환 타입을 사용하여 그 사실을 표현할 수 있다. 반환 값에 ? 물음표가 붙여 작성한다.  

 

if let bound {
   print("minValue = \(bound.min), maxValue = \(bound.max)")
}
// minValue = 1, maxValue = 10

✔️ 위의 예제와 같이 옵셔널 튜플 반환형 함수의 실제 값에 접근하려면 옵셔널 체인을 사용해야 한다.

 

함수 인자 라벨과 파라미터 이름 (Function Argument Labels and Parameter Names)
func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // 함수 내부에서 firstParameterName와 secondParameterName의 인자를 사용합니다.
}
someFunction(firstParameterName: 1, secondParameterName: 2)

✔️ 위의 예제와 같이 함수 호출시 적절한 파라미터 이름을 지정해 함수 내부와 함수 호출시 사용할 수 있다.

 

인자 라벨 지정 (Spectifying Argument Labels)
func someFunction(argumentLabel parameterName: Int) {
    // 함수 안애서 parameterName로 argumentLabel의 인자값을 참조할 수 있습니다.
}
func minFunc(a valueA : Int, b valueB : Int) -> Int {
    return valueA-valueB
}
print(minFunc(a:10, b:3))
// 7

✔️ 위의 예제와 같이 파라미터 앞에 인자 라벨을 지정해 실제 함수 내부에서 해당 인자를 식별하기 위한 이름과 함수 호출시 사용하는 이름을 다르게 해서 사용할 수 있다.

 

인자 생략 (Omitting Argument Labels)
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
    // 함수 안에서 firstParameterName, secondParameterName
    // 인자로 입력받은 첫번째, 두번째 값을 참조합니다.
}
someFunction(1, secondParameterName: 2)
func omittingMinFunc(_ valueA : Int, _ valueB : Int) -> Int {
    return valueA-valueB
}
print(omittingMinFunc(10, 5))
// 5

✔️ 위의 예제와 같이 파라미터 앞에 _를 붙여 함수 호출시 인자값을 생략할 수 있다.

 

기본 파라미터 값 (Default Parameter Values)
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // 함수 호출시 두번째 인자를 생략하면 함수안에서
    // parameterWithDefault값은 12가 기본 값으로 사용됩니다.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault는 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault는 12
func twiceFunc(a valueA: Int, valueB:Int=2) -> Int {
    return valueA*valueB
}
print(twiceFunc(a: 10))
// 20

✔️ 위의 예제와 같이 함수의 파라미터 값에 기본 값을 설정할 수 있다. 기본 값이 설정 되어 있는 파라미터는 함수 호출시 생략할 수 있다. 기본 값을 사용하지 않는 파라미터를 앞에 위치 시켜야 함수를 의미있게 사용하기 쉽다.

 

집합 파라미터(Variadic Parameters)
func allsumFunc(_ numbers:Int...) -> Int {
    var sumTotal: Int = 0
    for number in numbers {
        sumTotal += number
    }
    return sumTotal
}
print(allsumFunc(1, 2, 3))
// 6

✔️ 위의 예제와 같이 인자 값으로 특정 타입의 집합 값을 사용할 수 있다.

 

인-아웃 파라미터 (In-Out Parameters)
func swap(_ a: inout Int, _ b: inout Int) {
    let temp = a
    a = b
    b = temp
}

var someInt = 5
var anotherInt = 10
swap(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 10, and anotherInt is now 5"

✔️ 인자 값을 직접 변경하는 파라미터이다. 선언을 위해 파라미터 앞에 inout 키워드를 사용한다. inout 파라미터는 포인터를 넣는다고 생각하면 이해하기 쉽다.

⚠️ 인-아웃 파라미터는 기본 값을 갖을 수 없고, 집합 파라미터는 inout으로 선언될 수 없다. 인-아웃 파라미터를 사용하는 것은 함수의 반환 값을 사용하지 않고 함수 scope 밖에 영향을 줄 수 있는 또 하나의 방법이다.

 

 

함수 형 (Function Types)
func sumFunc(_ a: Int, _ b: Int) -> Int {
   return a + b
}

✔️ 위의 예제와 같이 함수의 형은 파라미터 형과 반환 형으로 구성 돼 있다. 위의 함수는 Int 값 두 개를 입력받고 Int를 반환하는 함수이다.

 

func printHelloWorld() {
    print("hello, world")
}

✔️ 위의 예제는 입력 받는 파라미터와 반환 값이 없는 함수이다.

 

함수 형의 사용 (Using Function Types)
func sumFunc(_ a: Int, _ b: Int) -> Int {
   return a + b
}
var mathFunction: (Int, Int) -> Int = sumFunc
print("Result: \(mathFunction(10, 5))")
// Result: 15

✔️ 위의 예제와 같이 함수를 변수처럼 정의해서 사용할 수 있다. 변수 mathFunction은 sumFunc함수의 인자 값과 반환 값이 같으므로 이 함수가 변수로 할당 될 수 있는 것이다. 

 

func sumFunc(_ a: Int, _ b: Int) -> Int {
   return a + b
}
let anotherMathFunction = sumFunc
print("Result: \(anotherMathFunction(1, 2))")
// Result: 3

✔️ 위의 예제와 같이 변수나 상수에 함수를 할당할 때 직접 함수 형을 선언하지 않아도 스위프트가 타입 추론을 통해 자동으로 함수를 할당할 수 있다.

 

파라미터 형으로써의 함수 형 (Function Types as Parameter Types)
func sumFunc(_ a: Int, _ b: Int) -> Int {
   return a + b
}

func printMathResult(_ paramFunc: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(paramFunc(a, b))")
}
printMathResult(sumFunc, 10, 5)
// Result: 15

✔️ 위의 예제와 같이 파라미터에 함수 형을 사용할 수 있다.

 

반환 형으로써의 함수 형 (Function Types as Return Types)
func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero는 이제 stepBackward() 함수를 가르키고 있습니다.
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

✔️ 위의 예제와 같이 함수를 반환하는 함수를 만들수도 있다.

 

중첩 함수 (Nested Functions)
func outerFunc(outValue: Int) -> String {
    func innerFunc(inValue:Int) -> String {
        return ("\(inValue)를 반환.")
    }
    let result = innerFunc(inValue: outValue+1)
    return result
}
print(outerFunc(outValue: 5))
// 6를 반환.

// 1. outerFunc호출시 outerFunc가 실행되고 return 값으로인해 innerFunc 함수가 실행 된다.
// 2. innerFunc 함수가 실행되면 innerFunc 안에 있는 return 값을 result에 저장한다.
// 3. result에 innerFunc에서 return한 값이 저장되어있고, result를 반환한다.

✔️ 위의 예제와 같이 함수 중에는 다른 함수 안의 body에서 동작하는 함수가 있는데 이를 중첩함수라고 한다. 중첩함수는 함수 밖에서는 감춰져 있고 함수의 body 내에서 접근할 수 있다.