함수의 역할이야 뭐.. C에서 워낙 많이 했으니까 생략하고
Swift는 함수 선언 방식이 좀 독특하다.
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
//반환값을 이렇게 만들어 짧게 할 수 있음
func greetAgain(person: String) -> String {
return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))
이런식으로 함수라는 것을 알려주는 func키워드를 제일 먼저, 함수명을 그 다음, 괄호에 매개변수 이름과 타입 적어주고, 반환값을 -> 로 연결하여 적음.
나머지 동작들은 C와 동일하게 { } 안에 적어주면 된다.
호출은 다음과 같이 하면 된다.
let result1: String = greet(person: "Anna")
print(result1)
// Prints "Hello, Anna!"
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"
이런 식으로 튜플을 만들어서 반환할 수도 있다.
물론 반환값에 튜플과 타입을 지정해 줘야 함.
사용은 튜플에 저장된 값을 사용하는 방식으로 사용이 가능하다.
반환값인 튜플 전체가 nil일 수 있을 때, optional tuple을 반환값으로 지정할 수 있다.
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)
}
//옵셔널 바인딩으로 반환값이 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"
함수 안 실행문이 하나밖에 없을 때 암시적으로 이것을 반환한다.
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!"
함수의 매개변수는 기본적으로 상수이다. 함수 안에서 매개변수의 값을 바꾸면 에러가 남.
만약 매개변수의 값을 수정하고, 함수 콜이 끝나고도 유지하고 싶다면, in-out 매개변수를 사용하면 된다.
이 in-out 매개변수 는 함수 안으로 들어와, 함수에 의해 변경되고, 뱉어져서 원래 값을 변경시키게 된다.
매개변수에는 변수로 선언된 것들만 넣을 수 있고, 상수나 literal value를 넣을 수 없다.
함수를 호출할 때 매개변수 이름 앞에다 & 를 써서, 이 변수들이 함수에 의해 변경될 것이라는 걸 알려준다. 약간 C의 포인터 느낌도 있는듯?
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"
이런 식으로 사용하면 된다.
이렇게 함수 밖에서 선언된 변수들의 값을 함수를 통해서 바꿀 수 있다.
Swift의 다른 자료형들처럼 함수도 자료형처럼 쓸 수 있다.
변수나 상수에 함수형을 넣을 수 있음.
그러면 해당 변수를 함수처럼 사용이 가능하다.
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
var mathFunction: (Int, Int) -> Int = addTwoInts
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5"
//swift의 타입 추론 덕분에 타입을 따로 쓰지 않아도 된다.
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (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"
사용할 때 해당 매개변수 자리에 동일한 타입의 함수를 전달해주면 됨.
함수의 반환값으로 함수를 넣을 수도 있다.
일반함수 두 가지를 정의해 두자.
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 함수는 반환값이 (Int) -> Int 이다.
즉 Int 매개변수를 하나 받아서 Int를 반환해주는 함수를 반환한다는 거임.
chooseStepFunction(backward: Bool) 에 따라
stepBackward(_:) 를 반환할지 stepBackward(_:) 를 반환할지가 정해진다.
사용은 다음과 같이 하면 된다.
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function
Nested Function(중첩 함수)는 말 그대로 함수 안에 들어간 함수를 말함.
제일 상위 함수 밖인 global에서는 숨겨지지만, 그 안에서는 실행 및 참조가 가능하다.
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!