[Swift 4.0] Functions

IOS/Swift 2017. 4. 1. 23:15

Defining and Calling Functions
: Swift 에서는 Function도 타입을 가질 수 있다. 타입을 구별하는 요소는 Function의 parameter type과 return type이다. 

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


Function Parameters and Return Values
: Swift Function의 parameter와 return value의 형태는 매우 다양하다. 이제 하나하나씩 알아볼 것이다.

Functions Without Parameters

return 값만 있고 parameter는 존재하지 않는 함수다.

func sayHellosWorld() -> String {
    reutrn "hello, world"
}

print(sayHelloWorld())

Functions With Multiple Parameters

여러개의 parameter와 return 값이 있는 function 이다.

func greet(person: String, alreadyGreeted: Bool) -> String {
    if alresyGreeted {
        return greetAgain(person: person)
    } else {
        return greet(person: person)
    }
}

print(greet(person: "Tim", alreadyGreeted: true))

이 함수는 우리가 위에서 정의한 greet(person:) 함수와 이름이 똑같다. 하지만 parameter의 타입이 다르기 때문에 서로 다른 타입으로 구별된다.

Functions Without Return Values

return Value를 갖지 않는 Function 이다.

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

greet(person: "Dave")

엄밀히 말하면, 위 함수는 값을 전혀 return하지 않는것이 아니고, Void type을 return한다. 이것은 empty tuple '()'로 표현될 수 있다.

Functions with Multiple Return Values
: return type으로 tuple을 지정할 수 있다.

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
: return type이 tuple인데 nil이 될 가능성이 있는경우 뒤에 '?'을 붙여서 optional type으로 만들어야 한다. 
단, (Int, Int)? 와 (Int?, Int?)는 구분해야 한다. 전자는 튜플 자체가 optional type이고 후자는 튜플안에 있는 각각의 타입이 optional type인 것이다.

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 "mins is -6 and max is 109"


Function Argument Labels and Parameter Names
: Function의 구성요소로 Argument Label과 Parameter Name이 있다.
Argument Label은 function을 call 할때 각각의 argument 앞에 붙여서 사용하고 parameter name은 함수 내부에서 넘어온 argument를 사용할 때 사용한다.
기본적으로 argument Label을 따로 지정해 주지 않으면 parameter name을 argument Label로 사용한다.

func someFunction(firstParameterName: Int, secondParameterName: Int)
{
    // 따로 argument Label을 지정해주지 않았으므로
    // firstParameterName, secondParameterName은 parameter name이 됨과 동시에 argument Label이 된다.
}

specifying Argument Labels
: Argument Label을 지정하는 경우를 살펴보자.

func someFunction(argumentLabel parameterName: Int) 
{
    // argument label이 지정된 경우이다. 함수 내부에서는 parameter name을 써야하고
    // 함수를 호출할 때에는 argument label을 사용해야 한다.
}

여러개의 parameter가 존재할 경우 argumentLabel을 일부 생략할 수도 있다.

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
: argument label을 사용하고 싶지 않다면 '_'을 추가해서 생략할 수 있다.

func someFunction(_ firstParameterName: Int, secondParameterName: Int)
{
    // body...
}

someFunction(1, secondParameterName: 2)

Default Parameter Values
: parameter에 Default value를 지정하는 방법을 알아보도록 하자.

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12)
{
    // body...
}

someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6)
someFunction(parameterWithoutDefault: 4) // 이 경우 두번째 parameter에 12가 자동 지정되어 함수가 호출된다.

Variadic Parameters
: 가변 갯수 파라미터를 뜻한다. 
가변 갯수 파라미터로 넘어오면 constant array로 취급된다.
함수는 최대 하나의 variadic parameter를 가질 수 있다.

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)
arithmeticMean(3, 8.25, 18.75)

In-Out Parameters
: 전산 전공자라면, 학부때 call-by-value, call-by-reference 개념을 배웠을 것이다.
swift는 함수의 parameter가 default로 상수(let)로 취급되고, 기본 타입(Int, Double . . . )이 구조체이기 때문에 call-by-value로 동작한다.
swift는 이러한 제약을 탈피하고자 In-Out Parameter라는 문법을 제공한다. 

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

in-out parameter로 상수, literal 값을 넘길 수 없다. 오직 변수(var)만 가능하다. 
또한, in-out parameter는 default 값을 가질 수 없고 variadic parameter는 in-out parameter가 될 수 없다. in-out parameter로 변수를 넘길 때 앞에 '&'을 붙여서 값이 변경될 것이라는 것을 표시한다. 

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"


Function Types
: 모든 function은 type을 가지고 있고, type은 parameter type과 return type에 의해 구별된다.

func addTwoInts(_ a: Int, _b: Int) -> Int 
{
    return a + b
}

func multiplyTwoInts(_ a: Int, _ b: Int) -> Int
{
    return a * b
}

두 함수의 타입은 (Int, Int) -> Int로 서로 같다.

Using Function Types
: function type은 다른 type들과 다를 것이 없다. 예를들어, function type의 변수, 상수를 만드는 것이 가능하다. 

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

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

mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 6"
// multiplyTwoInts는 addTwoInts와 같은 타입이니 같은 변수에 대입할 수 있다.

let anotherMathFunction = addTwoInts
// anotherMathFunction은 (Int, Int) -> Int 으로 타입추론 된다.

Function Types as Parameter Types
: function type을 parameter type으로 사용하여 function도 parameter로 넘길 수 있다.

func printMathResult(_ mathFunction: (Int, Int) -> Int, _a: Int, _ b:Int) 
{
    print("Result: \(mathFunction(a, b))")
}

printMathResult(addTowInts, 3, 5)
// Prints "Result: 8"

Function Types as Return Types
: function을 함수의 return type으로 사용할 수 있다.

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

func stepBackward(_ input: Int) -> Int 
{
    return - 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:")

while currentValue != 0
{
    print("\(currentValue)...")
    currentValue = moveNearerToZero(currentValue)
}

print("zero!")
// 3...
// 2...
// 1...
// zero!


Nested Functions
: Nested Function은 function안에 존재하는 function이다.
위 chooseStepFunction(backward:) 예제를 Nested Function을 통해 구현할 수 있다.

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!


'IOS > Swift' 카테고리의 다른 글

[Swift 4.0] Enumerations  (0) 2017.04.01
[Swift 4.0] Closures  (0) 2017.04.01
[Swift 4.0] Control Flow  (0) 2017.04.01
[Swift 4.0] Collection Types  (0) 2017.02.03
[Swift 4.0] Strings and Characters  (0) 2017.01.22
Posted by 홍성곤
,