가변인자
보통 함수는 정의된 형식과 개수에 맞는 인자값만 처리하지만, 때에 따라서 가변적인 개수의 인자값을 입력받아야할 경우도 분명 존재한다. 스위프트에선 인자값의 입력 개수를 제한하지 않도록 하는 함수 정의 형식을 제공하는데, 함수를 정의할 때 매개변수명 다음에 '...' 연산자를 추가하면된다.
func 함수명(매개변수명 : 매개변수타입...)
이런식으로 정의된 매개변수는 가변인자로 인식되며 개수를 제한하지 않고 인자값을 입력받게된다. 이렇게 입력된 인자값을 스위프트는 배열로 처리하게 된다. 다음 예시를 살펴보자.
func avg(score: Int...) -> Double {
var total = 0 // 점수 합계
for i in score { // 배열로 입려된 값들을 순회하며 점수 합산
total += i
}
return(Double(total) / Double(score.count)) // 평균값을 구해서 반환
}
print(avg(score: 10, 20, 30, 40))
/* 실행결과
25.0
매개변수 score는 가변인자로 설정된 Int 타입이다. 여기에 저장된 값은 배열로 처리되므로 [10, 20, 30, 40]이 매개상수 i에 하나씩 대입되어 for 구문을 반복 후 변수 total에서 합산한 점수를 그리고 score.count에서 배열에 아이템 개수를 나누어 평균값 25.0이 최종적으로 반환된다.
기본값을 갖는 매개변수
스위프트는 함수를 호출할 때 반드시 직접 입력받아야 하는 값이 아니면 인자값을 생략할 수 있도록, 함수 정의 시에 매개변수에 기본값을 지정할 수있는 문법을 제공한다. 이렇게 작성된 매개변수는 호출 시 인자값을 생략할 수 있다. 형식은 다음과 같다.
func 함수이름(매개변수: 매개변수타입 = 기본값) {
실행할 내용
}
대입 연산자 '='을 추가하고 기본값을 작성하는 형식이다. 이렇게 기본값이 입력된 매개변수는 인자값을 생략할 수 있다. 다음 예시를 보며 더 알아보자.
func echo(message: String, newline: Bool = true) {
if newline == true {
print(message, true)
} else {
print(message, false)
}
}
두 번째 매개변수인 newline은 줄바꿈 처리를하는 인자값을 받는다. 하지만 보통 줄바꿈 처리는 안 하는 경우보다 하는 경우가 많기 때문에 이렇게 기본값을 설정해두면 따로 값을 계속 처리를 해줄 필요가 없이 줄바꿈이 이루어진다.
// 두 개의 결과값이 같음
echo(message: "안녕하세요")
echo(message: "안넝하세요", newline: true)
// 줄바꿈 안하는 경우는 기본값과 다르니 표시를 해줘야함
echo(message: "안녕하세요", newline: false)
매개변수의 수정
함수의 매개변수에 입격된 인자값을 함수 내에서 수정하려고 하면 오류가 발생한다. 이것은 스위프트에서 함수의 인자값이 변수가 아니라 상수로 정의되기 때문이다. 사실 엄밀히 따지고 보면 매개변수가 아니라 매개상수라고 표현하는 것이 바람직하다.
// 입력받은 값을 +1 하여 리턴해주는 함수
func incrementBy(base: Int) -> Int {
base += 1
return base
}
여기서 함수의 매개변수인 base의 값에 +1을 해주어 반환해주는 것은 입력된 인자값에 대한 변경이 일어난다는 점이다. 이렇게 함수를 호출하여 실행하면 다음과 같은 오류가 발생한다.
"Left side of mutatig operator isn't operator isn't mutable : 'base' is a 'let' constant
오류 메시지를 해석해보면 "base는 상수로 정의되었으므로 왼쪽 수정연산자가 값을 변경할 수 없다"는 뜻인데 이처럼 함수의 인자값은 함수 내부에서 변수가 아니라 상수임에 주의해야한다. 인자값에 값을 할당하거나 수정하는 구문은 불가능하다는 뜻이다.
하지만 이렇게 상수로 정의되는 함수의 인자값이라 할지라도 내부에서 인자값을 수정하는 방법이 존재한다.
func incrementBy(base: Int) -> Int {
var base += base
base += 1
return base
}
이런식으로 동일한 이름의 변수를 작성해서 값을 대입하고 나면, 이후로 base 라는 이름의 호출은 모두 매개변수 base가 아니라 변수 base를 가리키게 된다. 여기에는 값을 수정하는 기존 구문을 그대로 사용해도 아무런 문제가 없다. 그저 변수의 값을 변경하는 것 뿐이니 말이다.
func descAge(name: String, _ paramAge: Int) -> String {
var name = name
var paramAge = paramAge
// 입력된 값을 변경한다.
name = name + "씨"
paramAge += 1
return "\(name)의 내년 나이는 \(paramAge)세 입니다"
}
앞의 예제와 비슷하지만 이번에는 매개변수가 두 개이다. 이 경우도 크게 다른 부분은 없다. 각각의 매개변수에 대해 변수화 하는 구문만 추가해주면 되기 때문이다. 사실 이 방식이라면 다른 변수명으로 정의하더라도 큰 상관은 없다.
출처 : 꼼꼼한 재은씨의 Swift 문법편
'Swift > 문법' 카테고리의 다른 글
스위프트(Swift) - 함수(Function) Ⅴ. 변수의 생존 범위와 생명 주기 (0) | 2022.05.18 |
---|---|
스위프트(Swift) - 함수(Function) Ⅳ. InOut 매개변수 (0) | 2022.05.17 |
스위프트(Swift) - 함수(Function) Ⅱ. 내부 매개변수, 외부 매개변수 (0) | 2022.05.13 |
스위프트(Swift) - 함수(Function) Ⅰ. 함수의 기본 개념 (0) | 2022.05.12 |
스위프트(Swift) - 옵셔널(Optional) (0) | 2022.05.11 |