스칼라 함수 파라미터의 다양한 형식과 함수 호출 방법 - 반복 매개변수 (Repeated parameter), 이름 지정 인수 (Named arguments), 기본 인수 (Default arguments)

View: 205 0 0
작성자: 달빛제이크
카테고리: Scala Language
발행: 2024-06-15 수정 2024-06-21

안녕하세요. 달빛제이크입니다.

이번 글에서는 함수 파라미터의 다양한 형식과 호출 방법에 대해서 알아보겠습니다.

함수 파라미터를 선언할 때는 보통 변수 이름에 타입을 지정하여 작성하는데, 스칼라 언어는 이와 같은 기본 형식 외에 추가로 세 가지 형식을 더 지원합니다.

1. Repeated parameters : 반복 매개변수, 반복 파라미터

2. Named arguments : 이름을 지정한 인수, 명명된 인수, 이름 지정 인수, 이름을 지정한 파라미터

3. Default parameter values : 기본 매개변수 값, 기본 파라미터 값

순서 대로 살펴 보겠습니다

1. Repeated parameters 반복 매개변수

함수를 호출할 때 함수에 전달하려는 인수의 개수가 상황에 따라 달라지는 경우가 있습니다.

전달하려는 인수에 값을 직접 입력하고 싶은데 개수가 다를 경우 Array, Seq, Map, Set과 같은 Collection으로 넘겨도 되지만, element 단위로 전달하는 기능을 지원합니다. 당연히 해당 인수의 Type은 동일해야 합니다.

Parameter를 선언할 때 변수 이름: 타입 명 바로 뒤에 *를 추가하면 해당 함수를 호출 할 때 동일한 타입의 인수를 개수에 상관없이 전달 할 수 있습니다.

// 정수들을 받아서 합계를 계산하는 함수 정의
def sum(nums: Int*): Int =
  var total = 0
  for num <- nums do
    total += num
  total

val result1 = sum(1, 2, 3, 4, 5)
println(result1)    // 15

var result2 = sum(10, 20)
println(result2)    // 30

val result3 = sum()
println(result3)    // 0

def sum2(nums: Int*): Int = nums.foldLeft(0)((x, y) => x+ y)
val result 4 = sum(20, 40)    // 60

sum 함수에 nums: Int*로 반복 매개변수를 선언해주고 sum 함수를 호출할 때 정수 타입의 값을 개수에 상관없이 전달하였습니다.
sum 함수의 내부 구현을 보면 for expression에서 collection이 동작하는 방식과 동일합니다. 맞습니다. 반복 매개변수는 인수를 Seq type으로 받아서 처리합니다. 인수를 Seq type으로 받는다고 Seq type으로 인수를 전달 할 수는 없습니다.

예제 마지막 부분에 있는 sum2 함수를 구현할 때 foldLeft를 써서 동일한 기능을 하도록 했습니다. foldLeft는 초기값을 지정해주고 연산 후의 결과를 왼쪽의 변수에 누적해서 반환하는 대표적인 고차 함수입니다. 함수를 호출하는 argument 부분이 특이한 데 이것은 Currying (커링)이라고 부르는 기능입니다. Currying에 대해서는 추후 다른 글에서 설명 드릴 예정입니다.

2. Named arguments 이름 지정 인수

함수를 호출할 때 보통 호출될 함수에서 정의한 매개변수의 순서에 맞추어 인수를 지정해야 합니다. 하지만 이름 지정 인수(Named arguments)를 사용하면 굳이 순서대로 인수를 지정하지 않아도 호출이 가능합니다. 또한 매개변수 이름이 있으니 각각의 인수가 어떤 변수에 할당되어 어떤 역할을 하는 지 쉽게 알 수 있어 가독성이 향상 됩니다.

def greet(name: String, greeting: String): String = s"$greeting, $name!"

// 인수의 순서 동일
val greeting1 = greet(name = "Alice", greeting = "Hello")
println(greeting1)    // Hello, Alice!

// 인수의 순서 변경
val greeting2 = greet(greeting = "Hi", name = "Bob")
println(greeting2)    // Hi, Bob!

여기서 s"..."는 String을 표현하는 형식 중 하나로 $기호를 사용해서 변수를 String 내부에서 사용할 수 있게 합니다. 변수 명이 단어 하나이면 $만 변수 명 앞에 추가하면 되는데, 변수 명이 객체의 필드여서 . (dot)를 통해 이어지거나 간단한 연산이 필요하다면 ${...} 와 같이 중괄호로 묶어 주면 됩니다.
예제를 통해 추가 설명 없이 Named argument를 쉽게 이해할 수 있을 것입니다.

3. Default parameter values 기본 매개변수 값

기본 매개변수 값 (Default parameter values)은 함수에 매개변수를 선언할 때 값을 지정해 주는 형식입니다. 값을 미리 지정해주면 값이 지정된 매개변수에 인수를 넘기지 않아도 해당 값이 매개변수에 할당되어 사용됩니다.
기본 매개변수 값을 사용할 때 앞 쪽 매개 변수에만 값을 할당하는 경우 앞 쪽 매개 변수에 해당하는 인수를 생략할 수 없기 때문에 보통 Named argument와 혼합해서 사용합니다.

// 모든 매개변수에 default value 지정
def greet(name: String = "Bob", greeting: String = "Hello") = s"$greeting, $name!"

val greeting1 = greet()
println(greeting1)    // Hello, Bob!

val greeting2 = greet("John")    // 인수가 앞 쪽 매개변수 name으로 전달 됨.
println(greeting2)    // Hello, John!

// 뒤 쪽 매개변수에 default value 지정
def greet(name: String, greeting: String = "Hello") = s"$greeting, $name!"

val greeting1 = greet()    // Error --> name 매개변수에 대한 인수가 필요함

val greeting2 = greet("Paulo")
println(greeting2)    // Hello, Paulo!

// 앞 쪽 매개변수에 default value 지정
def greet(name: String = "Bob", greeting: String) = s"$greeting, $name!"

val greeting1 = greet()    // Error --> greeting 매개변수에 대한 인수가 필요함

val greeting2 = greet("Jessica")    // Error --> 순서대로 name 변수에만 인수가 전달 됨. greeting 변수에 대한 인수가 없음

val greeting3 = greet(greeting = "Hi")    // Named argument를 사용
println(greeting3)    // Hi, Bob!

예제를 통해 Default parameter value에 대해 쉽게 이해 할 수 있을 것입니다.

지금까지 함수 파라미터의 형식과 함수 호출 방법에 대해서 알아보았습니다.

매우 간단한 문법이기 때문에 파라미터 순서 만 조심하면 크게 어려울 게 없습니다.

다음 글에서는 SAM (Single abstract method)에 대해서 이야기 하겠습니다.

감사합니다.

comments 0