[Swift5] Functions 2

Junyoung Park·2022년 2월 24일
0

Swift5 Docs

목록 보기
13/37
post-thumbnail
  • 다음은 Swift 5.6 Doc의 Functions 공부 내용을 정리했음을 밝힙니다.

Functions

함수 아규먼트 라벨과 파라미터 이름

함수의 파라미터는 아규먼트 라벨(argument label)과 파라미터 이름(parameter name)이 있다. 전자는 함수를 호출할 때, 후자는 함수를 사용할 때 사용한다. 일반적으로 파라미터는 파라미터 이름을 아규먼트 라벨로 사용한다.

모든 파라미터는 유니크한 이름이 있다. 여러 개의 파라미터의 아규먼트 라벨이 같을 수는 있지만, 유니크한 라벨을 사용하는 게 보다 가독성이 뛰어나다.

아규먼트 라벨 정하기

아규먼트 라벨을 파라미터 이름 전에 쓴다.

func func_example(argumentLabel parameterName: Int) {
	// Int the function body, parameterNmae refers to the argument value
    // for that parameter
}

func greet(person: String, from hometown: String) -> String {
	return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "LA"))
// Hello Bill! Glad you could visit from LA.

from hometownfromhometown이 각각 아규먼트 라벨과 파라미터 이름이다.

아규먼트 라벨을 통해 보다 가독성 있는 방식으로 코드를 작성할 수 있다.

아규먼트 라벨 생략

파라미터로 아규먼트 라벨을 사용하고 싶지 않을 때에는 언더스코어 _를 사용하면 된다.

func func_example(_ fistParameterName: Int, secondParameterName: Int){
	// In the function body, firstParameterName and secondParameterName
    // refers to the argument values for the first and second parameters.
}
func_example(1, secondParameterName:2)

디폴트 파라미터 값

파라미터 타입을 선언한 뒤 파라미터에 값을 할당하는 방법으로 디폴트 값을 설정할 수 있다. 디폴트 값이 있다면 함수를 선언할 때 이 파라미터에 값을 생략할 수도 있다.

func func_example(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.
}
func_example(parameterWithoutDefault: 3, parameterWithDefault: 6)
// each value: 3, 6
func_example(parameterWithoutDefault: 3)
// each value: 3, 12

함수가 맡은 주요 기능이 필요한 파라미터가 아니라면 디폴트 값을 설정해 편리해도 사용하자.

가변 파라미터

특정 타입의 데이터를 하나 이상 받아들일 수 있다. 파라미터에 입력되는 개수가 정확히 몇 개인지 사전에 정할 수 없을 때 ...라고 써서 가변 파라미터임을 표현할 수 있다.

받아들이는 데이터 타입이 정해졌다면 이 배열을 넘겨받는다고 이해할 수 있다.

가령 주어진 배열의 평균을 계산하는 계산기 함수를 선언한다고 하자.

func Calc(_ numbers: Double...) -> Double {
	var total: Double = 0
    for number in numbers{
    	total += number
    }
    return total / Double(numbers.count)
}
Calc(1, 2, 3, 4, 5)
// 3.0 returned

인-아웃 파라미터

함수 파라미터는 상수가 기본값이다. 파라미터로 입력받은 데이터를 바꾸는 건 런타임 에러를 발생시킨다. 그렇다면 입력받은 파라미터 값을 바꾸고, 함수 호출이 끝난 뒤에도 데이터를 바꾼 채로 유지하고 싶다면 어떻게 해야할까? 그런 파라미터를 인-아웃 파라미터로 정의하면 된다.

파라미터 타입 바로 전에 인아웃 inout이라는 키워드를 작성하자. 입력받은 파라미터 값이 함수 내에서 바뀐다면, 호출이 끝난 뒤 원본을 대체할 것이다. 함수를 호출할 때 원본 데이터 변수 앞에 and 연산자 & 기호를 사용하자.

func swap(_ a: inout Int, _ b: inout Int) {
	let tempA = a
    a = b
    b = tempA
}
var a = 10
var b = 20
swap(&a, &b)
// a: 20, b: 10 swapped

swap 함수가 리턴을 사용하지 않지만 인-아웃 파라미터를 통해 함수 내부에서 바깥 변수를 조정하고 있다.

함수 타입

함수에는 파라미터로 입력되는 데이터 타입, 리턴하는 데이터 타입이 있다.

func add(_ a: Int, _ b: Int) -> Int {
	return a + b
}
func Hello(){
	print("Hello, World!")
}

add 함수는 정수 파라미터 두 개를 입력값으로 받아들여 정수를 리턴하고, Hello 함수는 파라미터 없이 사용되며 리턴도 하지 않는다. 이 없다는 게 void임을 기억하자.

함수 타입 사용하기

변수나 상수를 함수 타입으로 선언해 할당할 수 있다.

var mathFunction: (Int, Int) -> Int = add

mathFunction이라는 변수는 두 개의 정수 값을 받아들여 정수를 리턴하며, 이 변수가 add라는 함수를 참조하도록 설정한다는 코드다.

스위프트 타입 체커라 불리는 이 할당 방식을 통해 우변의 함수가 좌변의 변수와 같은 타입인지 확인할 수 있다.

print("Result: \(mathFunction(2, 3))")
// Result: 5

타입 추론을 통해서도 사용 가능하다.

let anotherMathFunction = add
// anotherMathFunction: (Int, Int) -> Int

파라미터 타입의 함수 타입

(Int, Int) -> Int와 같은 함수 타입을 다른 함수에 사용할 파라미터로도 사용할 수 있다.

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int){
	print("Result: \(mathFunction(a, b))")
}
printMathResult(add, 1, 4)
// Result: 5

printMathResult 함수는 세 개의 파라미터를 가지고, 이 중 첫 번째 파라미터인 mathFunction이 앞서 설명한 함수 타입임을 확인하자. 에러가 나지 않도록 타입 매칭이 되도록 확인하자.

리턴 타입의 함수 타입

함수 타입을 다른 함수의 리턴 타입으로도 쓸 수 있다. 리턴 타입 연산자 -> 다음에 매칭될 함수 타입을 작성하자.

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)

stepForwardstepBackward 함수의 리턴 타입이 모두 (Int) -> Int임을 확인하자.
currentValue가 0보다 크기 때문에 0으로 이동하기 위해 두 개 함수 중 어떤 함수를 호출할지 택할 수 있다.

print("Counting to zero: ")
while currentValue != 0 {
	print("\(currentValue)...")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// Counting to zero:
// 3...
// 2...
// 1...
// zero!

중첩 함수

함수 안에 함수를 중첩해서(nested) 사용할 수도 있다.

중첩 함수는 기본적으로 함수 바깥에서는 숨겨져 있다. 중첩된 함수를 감싼(enclosing) 함수를 통해 접근, 사용하자.

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!
profile
JUST DO IT

0개의 댓글