Search

[Swift 공식 문서] 6. Functions

부제
카테고리
Swift
세부 카테고리
공식문서 번역
Combine 카테고리
최종편집일
2022/07/16 15:22
작성중
관련된 포스팅
생성 일시
2022/07/16 14:47
태그

Defining and Calling Functions

함수를 정의할 때, 파라미터의 이름을 한개 이상으로 정의할 수 있습니다. 리턴하고자 하는 값의 타입 또한 선택적으로 정의가 가능합니다.
함수의 인자들은 항상 함수의 파라미터 리스트의 순서와 동일하게 제공되어야 합니다.
다음은 함수정의의 예시입니다.
func greet(person: String) -> String { let greeting = "Hello, " + person + "!" return greeting }
Swift
복사
func 키워드로 함수의 이름과함께 정의합니다.
파라미터의 이름에 대해서는 반드시 type 을 지정해주어야하며 , 리턴타입역시 마찬가지입니다. 리턴 타입은 -> return arrow 뒤에 작성합니다.
print(greet(person: "Anna")) // Prints "Hello, Anna!" print(greet(person: "Brian")) // Prints "Hello, Brian!"
Swift
복사
greet() 의 리턴타입이 String 이므로 print() 함수에 인자로서 건네줄 수 있습니다.

Function Parameters and Return Values

Swift 의 함수 파라미터와 리턴 값은 매우 유연합니다. 한개부터 여러개의 파라미터를 가지는 복잡한 함수를 정의할수도 있습니다.

Functions Without Parameters

파라미터 없이도 함수를 정의할 수 있습니다.
파라미터가 없더라도 () 괄호를 써주어야합니다

Functions With Multiple parameters

쉼표로 구분된 여러 입력 파라미터를 정의할 수 있습니다.
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!"
Swift
복사

Functions With No Return Values

리턴 값 또한 선택적입니다. 굳이 사용하지 않아도 됩니다.
func greet(person: String) { print("Hello, \(person)!") } greet(person: "Dave") // Prints "Hello, Dave!"
Swift
복사
이 경우 값을 반환하지 않습니다.
엄밀히 말하면 값을 반환하지 않는 것이 아니라 Void 타입인 빈 튜플을 리턴합니다 ()
함수의 반환 값은 호출시 무시가능합니다.
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
Swift
복사
리턴값이 존재하는 함수이지만 무시됩니다
무시될 뿐이지 리턴하는 함수는 항상 리턴값을 반환합니다. 리턴값이 정의된 함수 내에서는 항상 return 키워드를 활용해 적절할 타입의 리턴 값을 반환해야하며, 그렇지 않으면 컴파일 에러가 발생합니다.

Functions with Multiple Return Values

튜플을 사용해서 여러개의 값을 반환할 수 있습니다.
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) }
Swift
복사
함수의 리턴 타입에 튜플의 member 에 대해 이름이 작성되어 있으므로 자동으로 bounds 에 .min , .max 로 각각의 값에 접근할 수 있습니다.
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"
Swift
복사
각각의 튜플들에게 따로 이름 붙일 필요가 없습니다.

Optional Tuple Return Types

리턴 타입이 tuple 인 함수로부터 어떠한 값도 반환되지 않을 가능성이 있다면, 이를 optional tuple 로 선언하여 사용하세요 ((Int, Int)? or (String, Int, Bool)?)
optional tuple 타입과 tuple 이 optional 한 타입을 포함하고 있는 경우는 서로 다른 경우입니다. optional tuple 같은 경우는 각각의 값의 존재여부가 optional 한것이 아니라, tuple 전체의 존재여부가 optional 하다는 것을 의미합니다.
위 코드에서도 인자로 건네받은 array 에 대해 어떠한 safety check 도 수행하지 않았음에 유념합시다.
만약 건네받은 array 가 비어있다면 위 함수에서는 런타임에러가 발생합니다.
따라서 아래와 같이 코드를 수정합니다.
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) }
Swift
복사
1.
리턴 타입을 optional tuple 타입으로 정의하였습니다.
2.
array 에 대해 safety check 을 한 뒤 함수의 실행이 불가능한 조건이라면 nil 값을 리턴하도록 정의하였습니다.
optional tuple 타입에 대해 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"
Swift
복사

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!"
Swift
복사
암묵적인 return 값을 사용하는 경우 반드시 값을 리턴하여야 합니다. fatalError("Oh no!") 또는 print(13) 의 사용이 불가합니다.

Function Argument Labels and Parameter Names

함수의 파라미터는 argument label 과 parameter name 을 둘다 가집니다. argument label 은 함수를 호출할 때 사용되고, parameter name 은 함수 내에서 사용됩니다.
기본적으로 파라미터는 parameter name 을 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)
Swift
복사
모든 파라미터는 반드시 유일한 이름을 가져야 합니다.

Specifying Argument Labels

Argument label 을 parmeter name 앞에 작성할 수 잇습니다.
func greet(person: String, from hometown: String) -> String { return "Hello \(person)! Glad you could visit from \(hometown)." } print(greet(person: "Bill", from: "Cupertino")) // Prints "Hello Bill! Glad you could visit from Cupertino."
Swift
복사
argument label 의 사용은 함수를 사용할 때 더 자연스러운 가독성을 제공합니다. 마치 하나의 문장처럼 말이지요.
따라서 함수의 파라미터의 의도를 파악하는 데 용이합니다.

Omitting Argument Labels

만약 파라미터에 대한 argument label 을 원하지 않는다면, _ 언더스코어를 활용해서 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)
Swift
복사

Default Parameter Values

파라미터에 초기값을 설정할 수 있습니다.
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
Swift
복사
이 경우 호출시 해당 파라미터에 대해서 인자를 건네주지 않아도 됩니다.
초기값이 있는 파라미터의 경우 호출시 전달 안해줘도 괜찮습니다.

Variadic Parameters

가변인자 타입 ... 키워드 사용
Variadic parameter 는 특정 타입의 가변인자(0개 ~ 여러개) 를 인자로 받습니다. vaiadic parameter 을 사용해서 parameter 에 여러개의 input value 를 건네줄 수 있습니다.
... 문자를 사용해서 Variadic parameter 를 정의할 수 있습니다.
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
Swift
복사
이렇게 선언된 Variadic parameter 는 함수 내부에서는 [Double] 타입으로 전달됩니다.
argument label 을 사용하면 variadic parameter 임을 더 명확히 나타낼 수 있습니다.

In-Out Parameters

when? : 주로 함수 바깥의 변수들을 변경해주고자 할 때.
how? : 변수 앞에 inout 키워드 작성 , 인자 앞에 & 기호 작성
함수의 매개변수는 기본적으로 constant입니다.
함수 내부에서 파라미터의 값을 변경하려 한다면, 컴파일 에러가 발생합니다.
1.
파라미터의 값을 변경하고자 하거나,
2.
함수가 호출된 후에도 파라미터를 사용하고자 한다면
in-out parameter 를 사용하세요
inout 키워드를 파라미터 타입 앞에 적어넣음으로서 사용이 가능합니다.
in-out 파라미터에 전달된 변수의 원본이 변경됩니다.
in - out parameter 에는 변수만 전달 가능!! 상수 또는 리터럴을 인자로 건네줄 수 없습니다.
func swapTwoInts(_ a: inout Int, _ b: inout Int) { let temporaryA = a a = b b = temporaryA }
Swift
복사
in-out parameter 는 초기값을 가질 수 없으며, variadic parameter 는 inout 으로 선언이 불가합니다.
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
복사
in out parameter 에 변수를 전달할 때는 & 기호를 사용해줍니다.
이를 통해 변수의 원본이 변경될 수 있음을 나타낼 수 있습니다.
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
복사

Function Types

모든 함수들은 특정한 타입을가집니다. 이 타입은 파라미터의 타입과 리턴 타입에 의해서 결정됩니다.
func addTwoInts(_ a: Int, _ b: Int) -> Int { return a + b } func multiplyTwoInts(_ a: Int, _ b: Int) -> Int { return a * b }
Swift
복사
위 예시에서 두함수의 타입은 (Int, Int) -> Int 로 같습니다.
func printHelloWorld() { print("hello, world") }
Swift
복사
위 코드의 타입은 () -> Void 입니다.

Using Function Types

함수의 타입을 여타 다른 타입들처럼 사용할 수 있습니다. 에를 들어 함수를 저장하는 상수 또는 변수를 정의해 할당할 수 있습니다.
var mathFunction: (Int, Int) -> Int = addTwoInts
Swift
복사
이렇게 할당된 변수를 함수처럼 사용도 가능합니다
print("Result: \(mathFunction(2, 3))") // Prints "Result: 5"
Swift
복사
타입을 명시하지 않을 경우 함수의 타입을 추론하여 변수 또는 상수의 타입을 정의합니다.
let anotherMathFunction = addTwoInts // anotherMathFunction is inferred to be of type (Int, Int) -> Int
Swift
복사

Function Types as Parameter Types

(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"
Swift
복사
타입을 만족하는 어떠한 함수든 전달이 가능해집니다.
type safe 한 방식으로 함수를 전달해줄 수 있습니다.

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) // moveNearerToZero now refers to the stepBackward() function print("Counting to zero:") // Counting to zero: while currentValue != 0 { print("\(currentValue)... ") currentValue = moveNearerToZero(currentValue) } print("zero!") // 3... // 2... // 1... // zero!
Swift
복사

Nested Functions 중첩 함수

함수안에 정의된 함수는 바깥에서 호출 불가 (단, 리턴은 가능)
위에서 배운 모든 함수들은 global 즉 전역함수입니다. 다른 함수의 body 에 다른 함수를 정의할 수 있으며 이를 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!
Swift
복사