함수를 ‘call’ 할 때 이름과 function 의 parameter 의 타입과 일치하는 input value (argument) 를 전달함.
// name : greet
// parameter : person
// return type : String
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
func prefix 키워드로 함수를 정의함. Return type 은 return arrow -> 로 표시함
Swift 에서 function parameters 과 return vlaue 는 유연하게 작성 가능
func sayHelloWorld() -> String {
return "hello, world"
}
print(sayHelloWorld())
// Prints "hello, world".
함수의 이름이 같아도 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!"
엄밀히 따지면 return value 가 정의되어 있지 않지만 Void 를 리턴하고 있음. Void 는 empty tuple.
func greet(person: String) {
print("Hello, \(person)!")
}
greet(person: "Dave")
// Prints "Hello, Dave!"
함수의 return value 는 무시할 수 있음. Return 된 값은 무시할 수 있지만 return value 가 있다고 정의된 함수는 항상 어떤 값을 return 해야 하고, 그렇지 않은 경우 compile-time error 발생
func printAndCount(string: String) -> Int {
print(string)
return string.count
}
func printWithoutCounting(string: String) {
let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting(string: "hello, world")
// prints "hello, world" but doesn't return a value
Tuple 을 사용해서 하나의 큰 return value 로 여러 값들을 리턴할 수 있음
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
}
}
// tuple 이 함수에서 return 될 때는 이름이 붙여질 필요 없음. (이미 함수의 return type 에 정의되어 있기 때문)
return (currentMin, currentMax)
}
// tuple member 값이 이름이 붙여져 있기 때문에 . syntax 로 접근할 수 있음
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".
함수에서 return 되는 tuple 이 전체 tuple 이 값이 없을 가능성이 있으면 optional tuple return type 을 사용해서 전체 tuple 이 nil 이 될 수 있음을 표시할 수 있음. e.g. (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)
}
// optional binding
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".
함수 body 전체가 하나의 expression 이라면 function 은 암묵적으로 해당 expression 을 return 함
func greeting(for person: String) -> String {
"Hello, " + person + "!"
}
print(greeting(for: "Dave"))
// Prints "Hello, Dave!"
// 가능. implicit return 이 일어나지 않음을 알고 있음
func greeting(for person: String) -> String {
fatalError()
}
각 function parameter 는 argument label, parameter name 이 있음.
Parameter는 기본적으로 parameter name 을 argument label 로 사용함. 모든 parameter 는 고유 이름을 가져야 하는데 여러 parameter 들이 같은 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)
Argument label 은 parameter name 앞에 씀
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
Underscore _ 을 써서 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)
Parameter 의 기본값을 설정할 수 있음. 기본값이 선언된 경우 함수를 호출할 때 해당 parameter 는 뺄 수 있음
기본 값이 없는 parameter 는 함수의 parameter list 의 앞부분에 위치해야 함. 기본 값이 없는 parameter 는 주로 함수에서 더 중요한 역할을 하고, 어떤 parameter 가 빠졌는지와 상관 없이 같은 함수가 호출되었다는 것을 더 알기 쉽게 해줌
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
// If you omit the second argument when calling this function, then
// the value of parameterWithDefault is 12 inside the function body.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12
Variadic parameter 는 0 개 이상의 값을 허용함. 함수를 호출할 때 parameter 의 개수가 달라질 수 있음을 명시하고 싶을 때 사용함. Parameter type 이름 다음에 three period characters ... 를 붙여서 작성
Variadic parameter 에 전달된 값들은 함수 body 내부에서 배열로 접근 가능.
함수는 여러 variadic parameter 는 가질 수 있음. Variadic parameter 다음에 오는 첫 번째 parameter 는 무조건 argument label 이 있어야 함.
func average(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
average(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
average(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
함수 parameter 는 기본적으로 상수. Parameter 를 함수 내부에서 값을 바꾸는 것은 compile-time error 발생시킴. 이는 parameter 의 값을 실수로 바꿀 수 없게 함. Parameter 의 값을 수정하고, 함수 호출이 끝난 후에 parameter 의 값을 수정한 것을 유지하고 싶으면 in-out parameter 로 정의
Parameter 타입 전에 inout 키워드를 써서 in-out parameter 씀. In-out parameter 는 함수에 전달되는 (in) 값을 가지고, 함수 내부에서 수정되며, 함수에서 다시 전달된 (out) 값을 갖고 원래의 값을 대체함.
함수의 in-out parameter 의 argument 로는 변수만 전달할 수 있음. 상수/literal value 를 argument 로 전달하면 걔네들은 수정될 수 없기 때문에 전달할 수 없음. 변수 이름 전에 ampersand & 를 붙여서 in-out parameter 임을 명시
In-out parameter 는 default value 를 가질 수 없고 variadic parameter 는 inout 으로 표기될 수 없음
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 이 있음.
Function type : parameter type, return type 으로 만들어짐
e.g.
// 두 개의 Int 를 받아 Int 를 리턴함
// (Int, Int) -> Int
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
// () -> Void
func printHelloWorld() { print("hello, world") }
Function type 은 다른 type 처럼 사용할 수 있음
// Define a variable which has a type of a function that takes two Int values, and return an Int value. Set this variable to refer to the function called addTwoInts
var mathFunction: (Int, Int) -> Int = addTwoInts
// 함수 호출
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5".
// 새로운 함수 할당
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 6".
Function type 을 다른 함수의 parameter type 으로 사용할 수 있음
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Prints "Result: 8".
Function type 을 다른 함수의 return type 으로 사용 가능
// (Int) 에 괄호가 없어지면 안됨
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward
}
함수 안에 함수, nested function 을 정의할 수 있음. <-> global function
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 now refers to the nested stepForward() function
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!