[Swift] 6. Function

도윤·2021년 7월 14일
0

Swift

목록 보기
6/21

Defining and Calling Functions

함수를 정의할 때 input으로써 취급하는 parameters을 선언할 수 있고, output값으로 취급하는 return type을 정의할 수 있다.

각 함수는 이름이 있고, 무슨 역할을 하는지 명시해야 한다.

 func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
}

return type은 (->) 로 한다.

Function paramerts and Return Values

이름이 지정되지 않은 단일 매개 변수를 사용하는 함수부터 매개 변수 이름과 다른 매개 변수 옵션을 사용하는 복잡한 함수도 선언할 수 있다.

Functions without Parameters

input parameters을 항상 선언할 필요는 없다

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

parameter을 가지지 않더라도 실행할때 ()를 붙여줘야 한다

Functions with multiple Parameters

여러개의 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!"

greet func은 String 타입의 파라미터와 Bool타입의 파라미터를 가진다.
이름이 같더라도 파라미터의 input타입이나 개수가 다르다면 다른 함수로 취급한다.

Functions Without Return Values

항상 Return type을 요구하지는 않는다.

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

return값을 필요로 하지 않기때문에 ->으로 Return type을 선언하지 않았다.

Functions With Multiple Return Type

여거래의 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)
}

Return에 지정한 min,max로 접근하면 된다.

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값이 return으로 반환될 수 있음을 Optional을 적용해서 알린다.(Int,Int)? or (String,Int,Bool)? 같이 사용하면 되며, (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)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
    print("min is \(bounds.min) and max is \(bounds.max)")
}

return 타입이 Optional이라면 반환할때도 Optional binding을 사용하여 값을 얻어야 한다.

Functions with implicit Return

함수의 내용의 전체 길이가 1줄이라면 그 함수는 그 줄을 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!"

내용이 한줄이라면 return type을 ->로 지정하지 않고 그 내용을 바로 return할 수 있다.


Functions Argument Labels and Paramters Names

Argument Label은 함수가 호출될 때 각각의 매개변수들의 입력값을 입력할 때 쓰인다.
Parameter Name은 함수구현할 때 사용된다. Argument Label이 정의되지 않으면 매개변수 이름으로 대체하여 사용한다. 모든 매개 변수는 고유의 이름을 가져야 한다

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 Arguemnt Labels

매개변수 앞에 argument label을 쓰면 된다.

func someFunction(argumentLabel parameterName: Int) {
    // In the function body, parameterName refers to the argument value
    // for that parameter.
}
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.

아래의 person은 argument label이 선언되지 않아서 parameter name으로 대신 사용되었고, homtown은 앞에 from이라는 argument label이 선언되어서 'from'으로 사용했다.

Omitting Argument Labels

Argument label을 사용하고 싶지 않다면 _으로 대체하여 사용하면 된다.

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

함수를 사용할 때 parameter를 선언하지 않으면 자동으로 적용될 default value를 함수 선언시 설정할 수 있다.

func someFunction(paramterWithoutDefault:Int, paramterWithDefault:Int = 12){
	//if you omit the second argument when calling this function,then
    //the value of paramterWithDefault is 12 inside the function body
}
someFunction(parameterWithoutDefault:3,paramterWithDefault:6)
//parameterWithDefault is 6
someFunction(parameterWithoutDefault:3)
//parameterWithDefault is 12

함수 선언시 default value를 선언하지 않을 parameter는 앞쪽에, 선언할 parameter는 뒤쪽응로 두는 것이 좋다.

Variadic Parameters

매개변수의 입력값에 0 또는 특정 타입의 여러값을 넣을 수 있다.
매개 변수 타입에 ...을 붙여서 사용하며, 이렇게 선언된 매개 변수는 함수 내에서 Array로 사용된다.

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

함수의 매개변수는 상수라서, 값을 변경하려고 한다면 Compile-error가 발생한다.
매개변수를 수정하고, 이를 함수가 끝난 후에도 유지하고 싶다면 in-out매개변수를 사용하면 된다.

매개변수 타입 앞에 inout키워드를 적어주면 사용이 가능하다.
매개변수를 상수타입 매개변수로 받고, 이 변수를 수정가능하도록 하기 위해 함수에서 다시 전달돼서 기존의 매개변수 값으로 대체하게 된다. 이렇기 때문에 In-Out 매개변수에는 변수(var)만 올 수 있다.
in-out 매개변수 호출을 사용할때는 변수의 이름 앞에 &를 사용하여 해당 변수가 함수내에서 수정될 수 있음을 알려야한다.

in-out 매개변수는 default값과 variadic 매개변수 사용 불가능.

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’

Function Type

모든 함수는 함수 타입을 가지는데, 이는 매개변수 타입과 반환값의 타입에 의해 결정된다.

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 Types

var mathFunction: (Int,Int)-> Int = addTwoInts
print("Result : \(mathFunction(2,3))")
//Prints "Result : 5"

위와 같이 함수를 변수나 상수에 저장 가능하다.

미리 선언된 변수에다가 새로운 함수로 바꿀수도 있다.

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

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

Function Type 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

기선언된 addTwoInts를 재활용하여 위의 코드로 사용 가능.
a,b의 입력을 받아 mathFunction을 사용할 수 있다.

Function Types as Return Type

함수 타입을 반환값으로도 사용 가능.

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 now refers to the stepBackward() function
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

ChooseStepFunction에서 backward가 true이면 함수 stepBackward를, false면 stepForward가 실행되도록 할 수 있다.


Nested Functions

함수를 중첩하는 방식으로, 내부에 중첩된 함수는 외부에서 사용할 수 없다. Enclosing 함수는 중첩 함수를 가지고 있는 함수를 말한다.

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!

위 함수를 중첩함수로 구현한 것이다.

0개의 댓글