함수는 작업을 처리하는 독립(self-contained) 코드 단위다. 함수 이름을 통해 선언할 수 있으며, 필요할 때마다 사용할 수 있다.
스위프트의 함수 문법은 파라미터에 이름을 주지 않는 C 언어 스타일부터 파라미터에 각 이름을 줘야 하는 Objective-C까지 모두 지원한다. 또한 파라미터에는 디폴트 값을 줄 수도 있다.
함수는 함수 내에 사용할 파라미터 타입과 함수가 반환할 리턴 타입을 사용한다. 함수 안에 또 다른 함수(nested)를 사용할 수도 있다.
함수 선언은 함수의 이름과 함수에 넘겨줄 파라미터를 정의하는 것부터 시작한다. 함수가 반환할 리턴 값이 존재한다면 리턴 타입을 정의할 수 있다.
함수를 사용할 때 이 함수를 선언(call)하는데, 이때 함께 괄호로 둘러싼 파라미터를 넘겨주게 된다. 함수 파라미터 리스트와 같은 순서대로 파라미터가 넘겨진다.
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
print(greet(person: "Junyeong"))
// Hello, Junyeong!
print(greet(person: "Park"))
// Hello, Park!
이 greet
함수에 파라미터로 넘겨준 문자열이 함수 내의 greeting
문자열 안에 사용되어 리턴된다. 파라미터로 넘겨주는 값에 따라 자연스럽게 리턴되는 문자열이 달라짐을 확인할 수 있다. ->
를 통해 이 함수가 반환할 타입을 명시한다.
함수 파라미터와 리턴 값은 매우 다양한 방법으로 사용된다.
함수는 입력 파라미터를 정의할 필요가 없다. 입력 파라미터가 없는 함수도 존재한다.
func sayHello() -> String {
return "Hello!"
}
print(sayHello())
// Hello
파라미터가 없는 sayHello()
를 선언하기 위해 아무 파라미터도 주지 않고 빈 괄호 그대로 선언한다.
반면 파라미터가 여러 개일 수도 있다. 콤마 ,
를 통해 파라미터를 구분해 넣자.
func greet(person: String, alreadyGreeted: Bool) -> String{
if alreadyGreeted {
return greetAgain(person: person)
} else {
return greet(person: person)
}
}
print(greet(person: "Junyeong", alreadyGreeted: true))
person
과 alreadyGreeted
라는 두 개 이상의 파라미터에 값을 넘겨줘야 함수를 실행할 수 있다.
함수는 리턴 값 또한 정의하지 않아도 된다.
func greet(person: String){
print("Hello, \(person)!")
}
greet(person: "Junyeong")
// Hello, Junyeong!
이 greet
함수는 입력 파라미터로 사람 이름을 밭아 인사하는 글만 출력하고는 그대로 종료한다.
튜플을 통해 이 함수에서 한 개 이상의 값을 리턴할 수 있다.
func minMax(array: [Int]) -> (min: Int, max: Int) {
var cur_min = array[0]
var cur_max = array[0]
for val in array[1..<array.count]{
if val < cur_min {
cur_min = val
} else if val > cur_max {
cur_max = val
}
}
return (cur_min, cur_max)
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print(bounds)
// (-6, 109)
minMax
함수는 두 개의 정수 값을 담은 튜플을 리턴 타입으로 삼고 있다. 입력값으로 배열을 받아 최댓값과 최솟값을 구해 이 두 개를 튜플로 반환하는 함수이다.
만일 리턴 값으로 줄 튜플이 값이 없을 수도 있다면, 옵셔널 타입을 사용하자. 옵셔널 튜플 리턴 타입은 이 튜플이 nil
일지도 모르는 상황에서 사용할 수 있다. 튜플 타입 끝 부분에 ?
를 붙여 이를 표시하자.
옵셔널 값을 튜플 내 값으로 담은 (Int?, Int?) 튜플과 (Int, Int)?라는 옵셔널 튜플 타입은 다르다. 각 개별 데이터가 옵셔널이라는 게 아니라, 튜플 전체가
nil
일 수도 있다는 뜻이기 때문이다.
앞의 minMax
함수 입력 파라미터가 빈 배열이라면 리턴 값 튜플은 빌 수도 있다. 옵셔널 튜플을 통해 이 상황을 커버하자.
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty {return nil}
var cur_min = array[0]
var cur_max = array[0]
for val in array[1..<array.count]{
if val < cur_min {
cur_min = val
} else if val > cur_max {
cur_max = val
}
}
return (cur_min, cur_max)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]){
print(bounds)
}
// (-6, 109)
이 경우 리턴 값이 nil
인 경우를 고려해 옵셔널 바인딩 if let binded_var = func() ~
을 사용하자.
함수 코드가 한 줄로 끝이라면 리턴을 생략할 수도 있다.
func greeting(for person: String) -> String {
"Hello, " + person + "!"
}
print(greeting(for: "Junyeong"))
// Hello, Junyeong!
한 줄이라면 return
코드를 생략해 짧게 표현할 수도 있다.