https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions
Swift 공식 문서 보면서 내 맘대로 정리
[다룰 내용들에 대한 요약]
- 함수는 특정 작업을 수행하는 독립적인 코드 블록
- 작업을 수행할 때, 함수의 이름을 사용하여 해당 함수를 "호출"한다.
- Swift의 함수 구문은 C 스타일 함수부터 각 파라미터에 이름과 레이블을 사용하는 Obj-C 스타일의 메서드까지 표현할 수 있을 정도로 유연하다.
- 파라미터는 기본 값을 가질 수 있어 함수 호출이 더 간단해지며, in-out 파라미터를 통해 함수가 실행된 후에 전달된 변수를 수정할 수 있다.
- Swift의 모든 함수는 타입을 가지고, 이 타입은 함수의 파라미터 타입과 반환 타입으로 정의된다.
- 함수 타입은 다른 함수에 파라미터로 전달하거나, 함수에서 반환할 수 있다.
- 함수는 다른 함수 안에 중첩되어 작성될 수 있으며, 이를 통해 특정 기능을 한정된 범위 내에서 캡슐화할 수 있다.
Function Parameters and Return Values
함수는 파라미터, 반환 값을 갖는다.
- 파라미터와 반환 값 모두 n개 이상을 갖는다 (n>=0)
- 반환 값이 없는 함수
- 엄밀히 말하면, 반환 값은 Void이다. Void는 사실상 빈 튜플인 ()와 같다.
func greet(person: String) {
print("Hello, \(person)!")
}
- 반환 값을 여러 개 가질 경우 튜플로 처리한다
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"
[Functions With an Implicit Return]
- 만약 함수 내용 전체의 길이가 한 줄이라면 그 줄이 return 값이 될 수 있다. (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!"
Function Argument Labels and Parameter Names
- Argument Label : 함수 호출 시 사용되는 이름
- Parameter Name : 함수 구현부 내에서 사용되는 이름
- Argument Label을 사용하면 함수가 표현력 있고, 문장 같은 방식으로 호출될 수 있으며, 구현부에서는 여전히 읽기 쉽고 의도가 명확하게 드러낼 수 있다.
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}
- Argument Label을 정의하지 않으면 파라미터 이름을 Argument label로 사용
- _ 를 Argument Label로 사용해 호출부에서 생략해 줄 수 있음
- 함수 정의부에서 default 값을 주면 호출부에서 파라미터를 생략할 수 있다.
- 이때 default를 정의해 준 파라미터들을 뒤쪽으로 두는 것이 좋다.
- default값이 없는 파라미터가 함수의 주요 동작에 있어 필수적인 값이기 때문에 앞에 둔다. 이렇게 하면 호출 시 필수적인 파라미터가 명확히 드러나고, default 값이 있는 파라미터는 생략 가능하여 코드를 더 간결히 작성할 수 있다.
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
- 가변 파라미터 뒤에 오는 첫 번째 파라미터는 Argument Label을 반드시 가져야 한다.
- 함수 호출 시 각 인자가 어떤 파라미터에 전달되는지 명확하게 하기 위함
func sumNumbers(_ numbers: Int..., multiplier: Int) -> Int {
let sum = numbers.reduce(0, +)
return sum * multiplier
}
생략하려고 하면 컴파일 에러 발생시켜 줌
In-Out Parameters
- 함수의 파라미터는 기본적으로 상수이다.
- 함수 본문 내에서 파라미터의 값을 변경하면 컴파일 에러가 발생
- 파라미터를 수정하고 싶고 이를 함수가 끝난 후에도 유지하고 싶다면 in-out 파라미터를 사용
- 이름 그대로 inout 파라미터는 함수에 들어와서 (in), 함수에 의해 수정되고, 함수 밖으로 다시 전달(out)되어 원래 값을 대체
- inout 파라미터의 동작과 관련된 자세한 내용은 여기서 정리
- 상수(let)나 리터럴 값이 아닌 변수(var)만 inout 파라미터로 전달 가능
- 상수와 리터럴 값은 수정될 수 없다.
- inout 파라미터에 전달할 때 함수에 의해 수정될 수 있음을 나타내기 위해 &를 변수명 앞에 배치
- inout 파라미터는 default 값을 가질 수 없다.
- inout 파라미터는 호출 시 반드시 변수로 전달되어야 하므로, 기본 값을 허용하지 않는다. &기호를 사용하여 참조를 전달하기 때문에, 기본 값을 설정하는 것은 논리적으로 맞지 않다.
- 가변 파라미터(variadic parameter)는 inout을 마킹할 수 없다.
- 가변 파라미터는 함수 본문에서 배열로 복사되어 사용되기 때문에, 참조로 전달되는 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 Types
- 모든 함수는 함수 타입을 갖는다.
- 이러한 함수 타입을 Swift의 다른 타입들처럼 사용할 수 있다.
- 변수 또는 상수처럼 사용할 수 있다.
- 다른 함수의 파라미터로 사용할 수 있다.
- 반환 값으로 사용할 수 있다.
[Using Function Types]
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 Types as Return Types]
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)
Nested Function
- 전역 범위에 정의된 함수가 아닌 다른 함수 내에 정의되는 함수
- 중첩 함수는 외부에서는 접근할 수 없다.
[중첩 함수 특징]
- 캡슐화 : 중첩함수는 자신을 둘러싸는 함수 내부에서만 사용할 수 있기 때문에 외부로부터 숨겨져 있다. 함수 내부의 로직을 잘게 나눠 캡슐화할 때 유용
- 변수 접근 : 중첩함수는 자신을 둘러싸는 함수의 변수와 상태에 접근할 수 있다. (단 중첩함수 선언이나 호출보다 앞선 라인에서 선언되어야 함)
func enclosingFunction() {
var num = 1
print("before nestedFunction called:", num)
// before nestedFunction called: 1
nestedFunction()
print("after nestedFunction called:", num)
// after nestedFunction called: 2
func nestedFunction() {
num += 1
}
}
enclosingFunction()
- 반환 가능 : 중첩함수는 둘러싸는 함수의 반환 값으로 사용될 수 있으며, 이 경우 외부에서 해당 중첩 함수를 사용할 수 있다.
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!
'iOS > Swift' 카테고리의 다른 글
Swift 공식문서 8. Enumeration (0) | 2024.10.03 |
---|---|
Swift 공식문서 7. Closures (3) | 2024.09.26 |
Swift - In-Out 파라미터 (0) | 2024.09.20 |
Swift 공식문서 5. Control Flow (0) | 2024.09.19 |
Swift - Strideable Protocol (0) | 2024.09.19 |