[Swift] Chapter01.Tour - 2
Functions and Closures
함수를 선언하기 위해서 func 을 사용한다. func의 뒤에 적히는 함수의 호출명과 괄호안에는 전달인자(argument)를 통해서 함수를 호출한다. 함수의 반환 유형에서 매개변수의 이름과 유형을 구분하려면 -> 을 사용한다.
func greet(person: String, day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet(person: "Bob", day: "Tuesday")
기본적으로 function은 매개변수의 이름을 전달인자의 label로 사용한다. 하지만 매개변수 앞에 사용자 지정 전달인자의 label을 작성하거나, _를 사용해서 사용자 지정 label을 사용하지 않을 수 있다.
func greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")
함수에서 여러 값을 반환하는 등의 동작을 하려면 튜플(tuple)을 사용한다. 튜플의 요소는 이름이나 번호로 참조 할 수 있다.
Tuple
여러 개의 값을 하나의 복합으로 묶을 수 있는 type. 각각의 값은 서로 다른 type일 수도 있고, 이름을 붙일 수도 있다.
let person = ("Tommy", 30)
print(person.0) // "Tommy"
print(person.1) // 30
let person = (name: "Tommy", age: 30)
print(person.name) // "Tommy"
print(person.age) // 30
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}
return (min, max, sum)
}
let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum)
// Prints "120"
print(statistics.2)
// Prints "120"
함수는 중칩될 수 있고, 중첩된 함수는 외부 함수에서 선언된 변수에 access 할 수 있다. 중첩된 함수를 사용하면 길거나 복잡한 코드를 간결하게 줄일 수 있다.
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
returnFifteen()
함수는 first-class type이다. 즉, 함수의 반환(return) 할때 다른 함수를 반환할 수 있다.
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(7)
함수는 다른 함수를 arguments로 받을 수 있다.
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: lessThanTen)
함수는 closer의 형태중 하나다. 클로저는 나중에 실행 할 수 있는 코드 블록을 의미하는데, 클로저 내부의 코드는 클로저가 만들어졌던 범위 안의 변수나 함수에 접근이 가능하다. 클로저를 사용할때는 이름 없이 중괄호 {}로 코드를 감싸면 클로저를 만들 수 있다. in 키워드를 사용해서 매개변수와 반환 타입을 본문과 구분 할 수 있다.
numbers.map({ (number: Int) -> Int in
let result = 3 * number
return result
})
func makeIncrementer(by amount: Int) -> () -> Int {
var total = 0
let incrementer: () -> Int = {
total += amount
return total
}
return incrementer
}
let incrementByTwo = makeIncrementer(by: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4
let greeting = {
print("Hello!")
}
greeting() // 실행
클로저를 간결하게 작성하기 위한 옵션이있다. 클로저의 유형을 다 알고있는 경우 매개변수의 유형, 반환 유형 또는 둘 다를 생략 할 수 있다. 단일 statement의 클로저는 암시적으로 단일 statement 값을 반환한다.
아래의 예시에서 number in 3 * number 는, number in return 3 * number를 생략한 것이다.
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
// Prints "[60, 57, 21, 36]
이름대신 매개변수를 번호로 참조 할 수 있는데, 매우 짧은 클로저에 유용하다. 함수의 마지막 인수로 전달된 클로저는 괄호 바로 뒤에 나타날 수 있다. 클로저가 함수의 유일한 인자인 경우 괄호를 생략할 수 있다.
let sortedNumbers = numbers.sorted { $0 > $1 }
print(sortedNumbers)
// Prints "[20, 19, 12, 7]