티스토리 뷰

프로그래밍언어/Swift

Swift 함수

데니 Denny 2020. 2. 23. 19:45
반응형
SMALL

이번 포스트에서는 Swift에서의 함수에 대해 알아보도록 하겠습니다.

 

Swift에서 함수를 생성하는 방법은 다음과 같습니다.

func 함수명(인자 이름: 타입) -> 리턴 타입 {
 (함수 본체)
 return (반환 값)
}

정의한 함수를 호출하는 방법은 다음과 같습니다.

func plus(num1: Int, num2: Int) -> Int {
	return num1 + num2
}

print(plus(1, 2))  // 3

함수의 Parameter Value와 Return Value

Parameter가 없는 함수

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

복수의 Parameter가 있는 함수

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

Return Value가 없는 함수

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

 

NOTE
위 함수는 반환 값을 선언하지는 않았지만 반환 값은 존재합니다. 반환 값이 정의 되지 않은 함수는 Void라는 특별한 타입을 반환합니다. Void는 간단히 ()를 사용한 빈 값(타입)입니다.

복수의 값을 Return 하는 함수

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

위 코드는 정수형 리스트를 파라미터로 받아서 최대 값과 최소 값을 튜플 형식으로 반환해주는 함수입니다.

옵셔널 튜플 반환 형

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과 같은 옵셔널 체인(Optional Chaining)을 사용하거나 강제 unwrapping을 해야 합니다.

함수 인자 레이블과 파라미터 이름

함수 호출시 적절한 파라미터 이름을 지정해 함수 내부와 함수 호출시 사용할 수 있습니다.

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

파라미터 레이블 지정 ( Specifying Arguments Label )

파라미터 앞에 인자 레이블을 지정해 실제 함수 내부에서 해당 인자를 식별하기 위한 이름과 함수 호출시 사용하는 이름을 다르게 해서 사용할 수 있습니다.

func someFunction(argumentLabel parameterName: Int) {
    // 함수 안애서 parameterName로 argumentLabel의 인자값을 참조할 수 있습니다.
}

아래 소스 코드는 Arguments Labels을 지정해서 함수 내부에서는 hometown으로 값을 제어하고 함수 호출시에는 인자 값으로 from을 사용한 예시 코드입니다.

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) {
    // 함수 안에서 firstParameterName, secondParameterName
    // 인자로 입력받은 첫번째, 두번째 값을 참조합니다.
}
someFunction(1, secondParameterName: 2)

기본 파라미터 값

함수의 파라미터 값에 기본 값(ex. test: Int = 12)을 설정할 수 있습니다. 기본 값이 설정 되어 있는 파라미터는 함수 호출시 생략할 수 있습니다. 기본 값을 사용하지 않는 파라미터를 앞에 위치 시켜야 함수를 의미있게 사용하기 쉽습니다.

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

집합 파라미터

인자 값으로 특정 형(type)의 집합 값을 사용할 수 있습니다.

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

인-아웃(Inout) 파라미터

인자 값을 직접 변경하는 파라미터 입니다. 선언을 위해 파라미터 앞에 inout 이라는 키워드를 사용합니다. 아래는 인자 두 값을 변경하는 함수입니다.

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

아래는 실제로 사용하는 예시 코드입니다. 함수의 인자에 변수를 넣을때 & 키워드를 넣었습니다. C언어를 해본 적이 있다면 inout파라미터는 포인터를 넣는다고 생각하면 좋을 것 같습니다.

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"

두 변수의 실제 값이 바뀐 것을 확인하실 수 있습니다.

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

함수 형 (Function Types)

함수의 형은 파라미터 형과(parameter types) 반환 형(return type)으로 구성 돼 있습니다. 아래 두 함수는 Int값 두 개를 입력받고 Int를 반환하는 함수입니다.

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

함수 형 (Function Type)의 사용

아래와 같이 함수를 변수처럼 정의해서 사용할 수 있습니다. 

var mathFunction: (Int, Int) -> Int = addTwoInts

변수 mathFunctionaddTwoInts 함수의 인자 값과 반환 값이 같으므로 이 함수가 변수로 할당 될 수 있습니다. 아래는 이렇게 변수에 함수를 할당해 사용한 예시 코드입니다.

print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5"

multiplyTwoInts 함수도 mathFunction과 함수 형이 같으므로 할당해 사용할 수 있습니다

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

Swift가 데이터의 타입을 자동으로 추론해(Type Inferred) 자동으로 함수를 할당할 수 있습니다.

(구체적으로 직접 타입을 지정할 필요가 없습니다.)

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

파라미터 타입으로 제공하는 함수 형 (Function Types as Parameter Types)

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

Swift에서는 함수의 파라미터로 함수 형을 넣어줄 수 있습니다.

반환형으로 제공하는 함수 형 (Function Types as Return Types)

Swift에서는 함수 형을 반환할 수도 있습니다.

func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}

입력한 step에 하나를 더하거나 빼는 함수를 선언했습니다. 이 함수를 리턴값으로 사용할 수 있습니다. 아래 코드는 backward함수가 truefalse냐에 따라 위에서 선언한 적절한 함수를 반환하는 함수입니다.

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

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero는 이제 stepBackward() 함수를 가르키고 있습니다.

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

print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

중첩 함수 (Nested Functions)

지금까지 함수는 전역적으로 동작하도록 선언했습니다.

함수 중에는 다른 함수 안의 body에서 동작하는 함수가 있는데 이 함수를 중첩 함수(Nested Function) 이라 합니다.

중첩함수는 함수 밖에서는 감춰져 있고 함수의 body내에서 접근 가능합니다.

위의 chooseStepFunction을 중첩 함수를 이용해 아래처럼 다시 작성할 수 있습니다.

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!

 

이번 포스트에서는 Swift의 함수에 대해 살펴봅았습니다.

반응형
LIST

'프로그래밍언어 > Swift' 카테고리의 다른 글

[Swift] Delegate 패턴 사용하기  (0) 2020.03.13
Swift 클로저 (Closure)  (0) 2020.02.23
Swift 메모리 안정성  (0) 2020.02.16
Swift 제어문 (조건문, 반복문)  (0) 2020.02.14
Swift Collection Types (컬렉션 타입)  (0) 2020.02.10
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
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
글 보관함