[Swift 공식문서 읽기]Functions

llim🧚🏻‍♀️·2021년 8월 11일
1

Swift

목록 보기
6/26
post-thumbnail

안녕하세요. 엘림입니다🙇🏻‍♀️

Swift 공식 문서 정독하기 6편입니다!

제 스타일대로 정리했으니 추가적으로 더 필요한 정보는
공식문서 링크를 눌러 확인해주세용!

좀 더 편하게 보기위해 한국어로 번역된 사이트를 함께 확인했습니다!ㅎㅎ

자, 그럼 시작해볼까요

이 글은 공부하면서 작성한 글이기 때문에 잘못된 정보가 있을 수 있습니다.🥺
금방 잊어버릴... 미래의 저에게 다시 알려주기 위한 글이다보니
혹시라도 틀린 부분이 있다면, 댓글로 친절하게 알려주시길 부탁드립니다.🙏


함수

함수는 특정 작업을 수행하는 코드 덩어리입니다.

정의 및 호출

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

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!"

위 함수에서 메시지를 결합하는 부분과 반환하는 부분을 합쳐서 더 짧게 만들 수 있습니다.

func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))
// Prints "Hello again, Anna!"

매개변수 및 반환 값

매개변수가 없는 함수

func sayHelloWorld() -> String {
    return "hello, world"
}
print(sayHelloWorld())
// Prints "hello, world"

복수의 매개변수가 있는 함수

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!"

반환 값이 없는 함수

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

func greet(person: String) {
    print("Hello, \(person)!")
}
greet(person: "Dave")
// Prints "Hello, Dave!"

함수의 반환 값은 아래와 같이 호출 될때 무시될 수 있습니다.

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 does not return a value

복수의 반환값이 있는 함수

func minMax(array: [Int]) -> (min: Int, max: Int, avg: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    var sum = 0
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
        sum += value
    }
    return (currentMin, currentMax, 10/array.count)
}

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max) and average is \(bounds.avg)")
// Prints "min is -6 and max is 109 and average is 1"

옵셔널 튜플 반환형

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)
}

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"

암시적 반환이 있는 함수

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

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!"

매개변수 이름 및 레이블

각 함수 매개변수에는 매개변수 레이블과 매개변수 이름이 있습니다. 매개변수 레이블은 함수를 호출할 때 사용됩니다. 매개변수 이름은 함수 구현에 사용됩니다. 기본적으로 매개변수는 매개변수 이름을 인수 레이블로 사용합니다.
(모든 매개변수는 고유한 이름을 가져야 합니다. 여러 매개변수에 동일한 매개변수 레이블이 있을 수 있지만 고유한 매개변수 레이블은 코드를 더 읽기 쉽게 만드는 데 도움이 됩니다.)

func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // 함수 내부에서 firstParameterName와 secondParameterName의 인자를 사용합니다.
}
someFunction(firstParameterName: 1, secondParameterName: 2)

레이블 지정

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."

인자 라벨을 지정해서 함수 내부에서는 hometown으로 값을 제어하고 함수 호출시에는 인자 값으로 from을 사용한 예입니다.

레이블 생략

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
    // 함수 안에서 firstParameterName, secondParameterName
    // 인자로 입력받은 첫번째, 두번째 값을 참조합니다.
}
someFunction(1, secondParameterName: 2)

기본 매개변수 값

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // 함수 호출시 두번째 인자를 생략하면 함수안에서
    // parameterWithDefault값은 12가 기본 값으로 사용됩니다.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault는 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault는 12

기본값이 있는 매개변수를 목록의 뒤쪽에 배치합니다. 기본값이 없는 매개변수는 일반적으로 함수의 의미에 더 중요합니다. 먼저 작성하면 기본 매개변수가 생략되었는지 여부에 관계없이 동일한 함수가 호출되고 있음을 더 쉽게 인식할 수 있습니다.

가변 매개변수

가변 매개변수는 지정된 유형의 0개 이상의 값을 수용합니다. 가변 매개변수를 사용하여 함수가 호출될 때 매개변수가 다양한 수의 입력 값을 전달할 수 있도록 지정합니다.

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 매개변수

함수 매개변수는 기본적으로 상수입니다. 해당 함수의 본문 내에서 함수 매개변수의 값을 변경하려고 하면 컴파일 시간 오류가 발생합니다. 이는 실수로 매개변수 값을 변경할 수 없음을 의미합니다. 함수가 매개변수 값을 수정하도록 하고 함수 호출이 끝난 후에도 이러한 변경 사항이 지속되도록 하려면 해당 매개변수를 In-Out 매개변수로 정의하십시오.
인-아웃 파라미터를 사용하는 것은 함수의 반환 값을 사용하지 않고 함수 scope 밖에 영향을 줄 수 있는 또 하나의 방법입니다.
(인-아웃 매개변수는 기본값을 가질 수 없으며 가변 매개변수로 표시할 수 없습니다.)

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

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"

함수 타입

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}
func printHelloWorld() {
    print("hello, world")
}

// 함수를 변수로 저장할 수 있음
var mathFunction: (Int, Int) -> Int = addTwoInts
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5"

mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 6"

let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int

변수 mathFunctionaddTwoInts함수의 인자 값과 반환 값이 같으므로 이 함수가 변수로 할당 될 수 있습니다. 변수나 상수에 함수를 할당할 때 직접 함수 형을 선언하지 않아도 Swift가 형을 추론해(Type Inferred) 자동으로 함수를 할당할 수 있습니다.

파라미터로 함수형

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Prints "Result: 8"

반환형으로 함수형

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!

moveNearerToZero를 호출할 때마다 stepBackward() 함수가 호출돼 입력 값이 1씩 줄어들어 결국 0이 됩니다.

중첩 함수

지금까지 함수는 전역적으로 동작하도록 선언했습니다. 함수 중에는 다른 함수 안의 body에서 동작하는 함수가 있는데 이 함수를 중첩 함수(Nested Function)라 합니다. 중첩함수는 함수 밖에서는 감춰져 있고 함수의 body내에서 접근 가능합니다.

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는 이제 중첩 돼 있는 stepForward() 함수를 가르킵니다.
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!

오늘은 스위프트 공식문서에서 Functions를 읽어보았습니다~
다음에는 Closures를 읽어보도록 하겠습니다!

감사합니다🙇🏻‍♀️

profile
한달 차 iOS 개발자입니다🐥

0개의 댓글