Functions

Groot·2022년 6월 7일
0

Swift Language Guide

목록 보기
5/24
post-thumbnail

Swift Language Guide - Functions

  • 함수는 특정 작업을 수행하는 자체 포함된 코드 덩어리입니다.
  • 함수가 하는 일을 식별하는 이름을 지정하면 이 이름은 필요할 때 작업을 수행하기 위해 함수를 "호출"하는 데 사용됩니다.
  • 이 유형을 Swift의 다른 유형과 같이 사용할 수 있으므로 함수를 매개변수로 다른 함수에 전달하고 함수에서 함수를 반환하기 쉽습니다.
  • 함수는 중첩된 함수 범위 내에서 유용한 기능을 캡슐화하기 위해 다른 함수 내에 작성할 수도 있습니다.

📌 Defining and Calling Functions

  • 함수를 정의할 때 매개변수라고 하는 함수가 입력으로 사용하는 하나 이상의 명명되고 유형이 지정된 값을 선택적으로 정의할 수 있습니다.
  • 함수가 완료되면 출력으로 다시 전달할 값 유형(반환 유형이라고 함)을 선택적으로 정의할 수도 있습니다.
  • 함수의 인수는 항상 함수의 매개변수 목록과 같은 순서로 제공되어야 합니다.
    func greet(person: String) -> String {
        let greeting = "Hello, " + person + "!"
        return greeting
    }
  • 정의는 함수가 무엇을 하는지, 무엇을 수신할 것으로 예상하는지, 완료되면 무엇을 반환하는지 설명합니다.
    print(greet(person: "Anna"))
    // Prints "Hello, Anna!"
    print(greet(person: "Brian"))
    // Prints "Hello, Brian!"

    print(_:separator:terminator:) 함수는 첫 번째 인수에 대한 레이블이 없고 다른 인수는 기본값이 있으므로 선택 사항입니다.

  • 이 함수의 본문을 더 짧게 만들기 위해 메시지 생성과 return 문을 한 줄로 결합할 수 있습니다.
    func greetAgain(person: String) -> String {
        return "Hello again, " + person + "!"
    }
    print(greetAgain(person: "Anna"))
    // Prints "Hello again, Anna!"

📌 Function Parameters and Return Values

  • 명명되지 않은 단일 매개변수가 있는 단순한 유틸리티 함수에서 표현 가능한 매개변수 이름과 다양한 매개변수 옵션이 있는 복잡한 함수에 이르기까지 무엇이든 정의할 수 있습니다.

📍 Functions Without Parameters

  • 함수는 입력 매개변수 정의를 요구하지 않습니다.
    func sayHelloWorld() -> String {
        return "hello, world"
    }
    print(sayHelloWorld())
    // Prints "hello, world"

📍 Functions With Multiple Parameters

  • 함수는 쉼표로 구분된 함수의 괄호 안에 작성되는 여러 입력 매개변수를 가질 수 있습니다.
    func greet(person: String, alreadyGreeted: Bool) -> String {
        if alreadyGreeted {
            return greetAgain(person: person)
        } else {
            return greet(person: person)
        }
    }
    print(greet(person: "Tim", alreadyGreeted: true))
    // Prints "Hello again, Tim!"

📍 Functions Without Return Values

  • 함수는 반환 유형을 정의를 요구하지 않습니다.
    func greet(person: String) {
        print("Hello, \(person)!")
    }
    greet(person: "Dave")
    // Prints "Hello, Dave!"
  • 값을 반환할 필요가 없기 때문에 함수의 정의에는 반환 화살표(->) 또는 반환 유형이 포함되지 않습니다.

    엄밀히 말하면 이 버전의 welcome(person:) 함수는 반환 값이 정의되어 있지 않아도 여전히 값을 반환합니다.
    정의된 반환 유형이 없는 함수는 Void 유형의 특수 값을 반환합니다. 이것은 ()로 쓰여진 단순히 빈 튜플입니다.

  • 함수의 반환 값은 호출될 때 무시할 수 있습니다.
    func printAndCount(string: String) -> Int {
        print(string)
        return string.count
    }
    func printWithoutCounting(string: String) {
        let _ = printAndCount(string: string)
    }
    printAndCount(string: "hello, world")
    // prints "hello, world" and returns a value of 12
    printWithoutCounting(string: "hello, world")
    // prints "hello, world" but doesn't return a value
  • 첫 번째 함수인 printAndCount(string:)는 문자열을 인쇄한 다음 해당 문자 수를 Int로 반환합니다. 두 번째 함수인 printWithoutCounting(string:)은 첫 번째 함수를 호출하지만 반환 값은 무시합니다.
  • 두 번째 함수가 호출될 때 메시지는 여전히 첫 번째 함수에 의해 인쇄되지만 반환된 값은 사용되지 않습니다.

    반환 값은 무시할 수 있지만 값을 반환한다고 말하는 함수는 항상 반환을 해야 합니다.
    정의된 반환 유형이 있는 함수는 값을 반환하지 않고 함수가 끝나는 것을 허용할 수 없으며 그렇게 하려고 하면 컴파일 시간에 오류가 발생합니다.

📍 Functions with Multiple Return Values

  • 튜플 유형을 함수의 반환 유형으로 사용하여 하나의 복합 반환 값의 일부로 여러 값을 반환할 수 있습니다.
    func minMax(array: [Int]) -> (min: Int, max: Int) {
        var currentMin = array[0]
        var currentMax = array[0]
        for value in array[1..<array.count] {
            if value < currentMin {
                currentMin = value
            } else if value > currentMax {
                currentMax = value
            }
        }
        return (currentMin, currentMax)
    }
  • 튜플의 멤버 값은 함수의 반환 유형의 일부로 이름이 지정되기 때문에 발견된 최소 및 최대 값을 검색하기 위해 점 구문으로 액세스할 수 있습니다.
    let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
    print("min is \(bounds.min) and max is \(bounds.max)")
    // Prints "min is -6 and max is 109"
  • 튜플의 멤버는 이름이 이미 함수의 반환 유형의 일부로 지정되어 있기 때문에 함수에서 튜플이 반환되는 지점에서 이름을 지정할 필요가 없습니다.

📍 Optional Tuple Return Types

  • 함수에서 반환되는 튜플 유형이 전체 튜플에 대해 "값 없음"을 가질 가능성이 있는 경우, 전체 튜플이 nil일 수 있다는 사실을 반영하기 위해 선택적 튜플 반환 유형을 사용할 수 있습니다.
  • 튜플 유형의 닫는 괄호 뒤에 물음표를 넣어 선택적 튜플 반환 유형을 작성합니다.
  • (Int, Int)? or (String, Int, Bool)?

    (Int, Int)와 같은 선택적 튜플 유형 (Int?, Int?)와 같은 선택적 유형을 포함하는 튜플과 다릅니다. 선택적 튜플 유형을 사용하면 튜플 내의 개별 값뿐만 아니라 전체 튜플이 선택 사항입니다.

    func minMax(array: [Int]) -> (min: Int, max: Int)? {
        if array.isEmpty { return nil }
        var currentMin = array[0]
        var currentMax = array[0]
        for value in array[1..<array.count] {
            if value < currentMin {
                currentMin = value
            } else if value > currentMax {
                currentMax = value
            }
        }
        return (currentMin, currentMax)
    }
  • 선택적 바인딩을 사용하여 이 버전의 minMax(array:) 함수가 실제 튜플 값을 반환하는지 아니면 nil을 반환하는지 확인할 수 있습니다.
    if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
        print("min is \(bounds.min) and max is \(bounds.max)")
    }
    // Prints "min is -6 and max is 109"

📍 Functions With an Implicit Return

  • 함수의 전체 본문이 단일 표현식인 경우 함수는 암시적으로 해당 표현식을 반환합니다. 예를 들어 아래의 두 함수는 모두 동일한 동작을 합니다.

    func greeting(for person: String) -> String {
        "Hello, " + person + "!"
    }
    print(greeting(for: "Dave"))
    // Prints "Hello, Dave!"
    
    func anotherGreeting(for person: String) -> String {
        return "Hello, " + person + "!"
    }
    print(anotherGreeting(for: "Dave"))
    // Prints "Hello, Dave!"
  • 하나의 리턴 라인으로 작성하는 모든 함수는 리턴을 생략할 수 있습니다.

    암시적 반환 값으로 작성하는 코드는 일부 값을 반환해야 합니다. 예를 들어, 암시적 반환 값으로 print(13)을 사용할 수 없습니다.
    그러나 Swift는 묵시적 반환이 발생하지 않는다는 것을 알고 있기 때문에 fatalError("Oh no!")와 같이 절대 반환하지 않는 함수를 묵시적 반환 값으로 사용할 수 있습니다.


📌 Function Argument Labels and Parameter Names

  • 각 함수 매개변수에는 인수 레이블과 매개변수 이름이 모두 있습니다.
  • 인수 레이블은 함수를 호출할 때 사용됩니다.
  • 각 인수는 그 앞에 인수 레이블이 있는 함수 호출에 기록됩니다.
  • 매개변수 이름은 함수 구현에 사용됩니다.
  • 기본적으로 매개변수는 매개변수 이름을 인수 레이블로 사용합니다.
    func someFunction(firstParameterName: Int, secondParameterName: Int) {
        // In the function body, firstParameterName and secondParameterName
        // refer to the argument values for the first and second parameters.
    }
    someFunction(firstParameterName: 1, secondParameterName: 2)
  • 모든 매개변수는 고유한 이름을 가져야 합니다.
  • 여러 매개변수가 동일한 인수 레이블을 가질 수 있지만 고유한 인수 레이블은 코드를 더 읽기 쉽게 만드는 데 도움이 됩니다.

📍 Specifying Argument Labels

  • 공백으로 구분하여 매개변수 이름 앞에 인수 레이블을 작성합니다.
    func someFunction(argumentLabel parameterName: Int) {
        // In the function body, parameterName refers to the argument value
        // for that parameter.
    }
  • 다음은 사람의 이름과 고향을 받아 인사말을 반환하는 Greeting(person:) 함수의 변형입니다.
    func greet(person: String, from hometown: String) -> String {
        return "Hello \(person)!  Glad you could visit from \(hometown)."
    }
    print(greet(person: "Bill", from: "Cupertino"))
    // Prints "Hello Bill!  Glad you could visit from Cupertino."
  • 인수 레이블을 사용하면 함수를 문장과 같은 표현 방식으로 호출할 수 있으며 가독성이 좋고 의도가 명확한 함수 본문을 제공할 수 있습니다.

📍 Omitting Argument Labels

  • 매개변수에 대한 인수 레이블을 원하지 않으면 해당 매개변수에 대한 명시적 인수 레이블 대신 밑줄(_)을 작성하십시오.
    func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
        // In the function body, firstParameterName and secondParameterName
        // refer to the argument values for the first and second parameters.
    }
    someFunction(1, secondParameterName: 2)
  • 매개변수에 인수 레이블이 있는 경우 함수를 호출할 때 인수에 레이블을 지정해야 합니다.

📍 Default Parameter Values

  • 해당 매개변수의 유형 다음에 매개변수에 값을 할당하여 함수의 모든 매개변수에 대한 기본값을 정의할 수 있습니다.
  • 기본값이 정의되어 있으면 함수를 호출할 때 해당 매개변수를 생략할 수 있습니다.
    func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
        // If you omit the second argument when calling this function, then
        // the value of parameterWithDefault is 12 inside the function body.
    }
    someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
    someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12
  • 기본값이 없는 매개변수는 함수의 매개변수 목록 시작 부분에, 기본값이 있는 매개변수 앞에 배치합니다.
  • 기본값이 없는 매개변수는 일반적으로 함수의 의미에 더 중요합니다.
  • 기본값이 있는 매개변수 먼저 작성하면 기본 매개변수가 생략되었는지 여부에 관계없이 동일한 함수가 호출되고 있음을 더 쉽게 인식할 수 있습니다.

📍 Variadic Parameters

  • 가변 매개변수는 지정된 유형의 0개 이상의 값을 허용합니다.
  • 가변 매개변수를 사용하여 함수가 호출될 때 매개변수가 다양한 수의 입력 값을 전달할 수 있도록 지정합니다.
  • 매개변수 유형 이름 뒤에 세 개의 마침표(...)를 삽입하여 가변 매개변수를 작성합니다.
  • 가변 매개변수에 전달된 값은 함수 본문 내에서 적절한 유형의 배열로 사용할 수 있습니다.
  • 예를 들어 이름이 숫자이고 Double... 유형인 가변 매개변수는 [Double] 유형의 숫자라는 상수 배열로 함수 본문 내에서 사용할 수 있습니다
    func arithmeticMean(_ numbers: Double...) -> Double {
        var total: Double = 0
        for number in numbers {
            total += number
        }
        return total / Double(numbers.count)
    }
    arithmeticMean(1, 2, 3, 4, 5)
    // returns 3.0, which is the arithmetic mean of these five numbers
    arithmeticMean(3, 8.25, 18.75)
    // returns 10.0, which is the arithmetic mean of these three numbers
  • 함수는 여러 가변 매개변수를 가질 수 있습니다.
  • 가변 매개변수 다음에 오는 첫 번째 매개변수에는 인수 레이블이 있어야 합니다.
  • 인수 레이블은 가변 매개변수에 전달되는 인수와 가변 매개변수 다음에 오는 매개변수에 전달되는 인수를 명확하게 합니다.

📍 In-Out Parameters

  • 함수 매개변수는 기본적으로 상수입니다.
  • 함수가 매개변수의 값을 수정하도록 하고 함수 호출이 끝난 후에도 이러한 변경 사항을 유지하려면 해당 매개변수를 in-out 매개변수로 대신 정의하십시오.
  • 매개변수 유형 바로 앞에 inout 키워드를 배치하여 in-out 매개변수를 작성합니다.
  • in-out 매개변수에는 함수에 전달되고 함수에 의해 수정되며 원래 값을 대체하기 위해 함수 외부로 다시 전달되는 값이 있습니다.
  • 인-아웃 매개변수의 동작 및 관련 컴파일러 최적화에 대한 자세한 내용은 In-Out Parameters를 참조하세요.
  • 변수는 in-out 매개변수에 대한 인수로만 전달할 수 있습니다. 상수 또는 리터럴 값을 인수로 전달할 수 없습니다.
  • 함수에 의해 수정될 수 있음을 나타내기 위해 in-out 매개변수에 인수로 전달할 때 변수 이름 바로 앞에 앰퍼샌드(&)를 배치합니다.

    In-out 매개변수는 기본값을 가질 수 없으며 가변 매개변수는 inout으로 표시할 수 없습니다.

  • 다음은 a와 b라는 두 개의 in-out 정수 매개변수가 있는 swapTwoInts(::)라는 함수의 예입니다.
    func swapTwoInts(_ a: inout Int, _ b: inout Int) {
        let temporaryA = a
        a = b
        b = temporaryA
    }
  • Int 유형의 두 변수를 사용하여 swapTwoInts(::) 함수를 호출하여 값을 바꿀 수 있습니다.
  • someInt 및 anotherInt의 이름은 swapTwoInts(::) 함수에 전달될 때 앰퍼샌드가 접두사로 붙습니다.
    ```swift
    var someInt = 3
    var anotherInt = 107
    swapTwoInts(&someInt, &anotherInt)
    print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
    // Prints "someInt is now 107, and anotherInt is now 3"
    ```

    인-아웃 매개변수는 함수에서 값을 반환하는 것과 다릅니다. 위의 swapTwoInts 예제는 반환 유형을 정의하거나 값을 반환하지 않지만 여전히 someInt 및 anotherInt의 값을 수정합니다.
    인-아웃 매개변수는 함수가 함수 본문의 범위 외부에서 영향을 미치도록 하는 대체 방법입니다.


📌 Function Types

  • 모든 함수에는 매개변수 유형과 함수의 반환 유형으로 구성된 특정 함수 유형이 있습니다.
    func addTwoInts(_ a: Int, _ b: Int) -> Int {
        return a + b
    }
    func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
        return a * b
    }
  • 이 두 함수의 유형은 (Int, Int) -> Int입니다.
    func printHelloWorld() {
        print("hello, world")
    }
  • 이 함수의 유형은 () -> Void입니다.

📍 Using Function

  • Swift의 다른 유형과 마찬가지로 함수 유형을 사용합니다.
  • 상수 또는 변수를 함수 유형으로 정의하고 해당 변수에 적절한 함수를 할당할 수 있습니다.
    var mathFunction: (Int, Int) -> Int = addTwoInts
  • 이것은 다음과 같이 읽을 수 있습니다. "'두 개의 Int 값을 취하고 Int 값을 반환하는 함수' 유형의 mathFunction이라는 변수를 정의합니다. 이 새 변수를 addTwoInt라는 함수를 참조하도록 설정합니다."
  • 이제 MathFunction이라는 이름으로 할당된 함수를 호출할 수 있습니다.
    print("Result: \(mathFunction(2, 3))")
    // Prints "Result: 5"
  • 일치하는 유형이 같은 다른 함수를 함수가 아닌 유형과 동일한 방식으로 동일한 변수에 할당할 수 있습니다.
    mathFunction = multiplyTwoInts
    print("Result: \(mathFunction(2, 3))")
    // Prints "Result: 6"
  • 다른 유형과 마찬가지로, 상수나 변수에 함수를 할당할 때 함수 유형을 유추하기 위해 Swift에 맡길 수 있습니다.
    let anotherMathFunction = addTwoInts // anotherMathFunction은 (Int, Int) -> Int 유형으로 추론됩니다.

📍 Function Types as Parameter Types

  • (Int, Int) -> Int와 같은 함수 유형을 다른 함수의 매개변수 유형으로 사용할 수 있습니다.
    func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
        print("Result: \(mathFunction(a, b))")
    }
    printMathResult(addTwoInts, 3, 5)
    // Prints "Result: 8"

📍 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
    }
  • chooseStepFunction(backward:) 함수는 뒤로 호출되는 부울 매개변수를 기반으로 stepForward(:) 함수 또는 stepBackward(:) 함수를 반환합니다.


📌 Nested Functions

  • 지금까지 이 장에서 만난 모든 함수는 전역 범위에서 정의된 전역 함수의 예입니다.
  • 중첩 함수라고 하는 다른 함수의 본문 내부에 함수를 정의할 수도 있습니다.
  • 중첩된 함수는 기본적으로 외부 세계에서 숨겨져 있지만 여전히 둘러싸는 함수에서 호출하고 사용할 수 있습니다.
  • 둘러싸는 함수는 중첩된 함수 중 하나를 반환하여 다른 범위에서 중첩된 함수를 사용할 수도 있습니다
  • 위의 chooseStepFunction(backward:) 예제를 다시 작성하여 중첩 함수를 사용하고 반환할 수 있습니다.
    func chooseStepFunction(backward: Bool) -> (Int) -> Int {
        func stepForward(input: Int) -> Int { return input + 1 }
        func stepBackward(input: Int) -> Int { return input - 1 }
        return backward ? stepBackward : stepForward
    }
    var currentValue = -4
    let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
    // moveNearerToZero now refers to the nested stepForward() function
    while currentValue != 0 {
        print("\(currentValue)... ")
        currentValue = moveNearerToZero(currentValue)
    }
    print("zero!")
    // -4...
    // -3...
    // -2...
    // -1...
    // zero!
profile
I Am Groot

0개의 댓글