본문 바로가기

Data Engineering/Scala

가변 파라미터(variable arguments)를 받는 메소드

스칼라로 가변적인 개수의 파라미터를 받는 메소드 만들기 & 사용하기

메소드를 선언할 때는 파라미터 타입 뒤에 * 문자를 붙인다.

scala> def printAll(args: String*) = args.foreach(println)

scala> printAll("hello")
hello

scala> printAll("hello", "world", "!")
hello
world
! 

메소드를 사용할 때는 위의 예시처럼 하나하나 직접 넘겨도 되지만 보통 List, Array와 같은 Iterable 타입의 변수를 넘긴다. 하지만 그냥 Iterable을 넘기면 컴파일 에러가 난다.

scala> val l = List("hello", "world")
scala> printAll(l)
<console>:28: error: type mismatch;
 found   : List[String]
 required: String
       printAll(l)
                ^

required: String 인 것으로 보아, 리스트를 풀어서 하나 하나 넘겨야하는 것 같다. 이걸 해주는 심볼이 바로 _* 다. 영어로는 vararg expansion 이라고 부른다. 스칼라에서는 파라미터 뒤에 : Type 을 붙여 타입을 나타낼 수 있는데, 컴파일러는 : _* 을 통해 해당 파라미터가 vararg expansion 해야하는 파라미터임을 알 수 있다.

scala> printAll(l: _*)
hello
world

이런 가변 파라미터 필드는 함수 선언시에 항상 마지막에 와야한다. 그래야 파라미터를 구분할 수 있으니까 (...) 한발 더 나가 생각해보면, 모든 메소드에는 늘 하나의 varargs 만 선언할 수 있다.

// OK
scala> def printAll(v: Int, args: String*) = {...}

// ERROR: varargs parameter은 제일 마지막에 와야한다.
scala> def printAll(args: String*, v: Int) = {...}
<console>:23: error: *-parameter must come last

내부적으로는 WrappedArray 처리를 해서, 아무것도 들어오지 않으면 해당 파라미터는 결과적으로 빈 시퀀스(== Nil)가 된다.

scala> def printAll(args: String*) = println(args)

scala> printAll("hello", "world")
WrappedArray(hello, world)

scala> printAll()
List()

참고문서

- https://alvinalexander.com/scala/how-to-define-methods-variable-arguments-varargs-fields

- https://docs.scala-lang.org/tutorials/FAQ/finding-symbols.html

'Data Engineering > Scala' 카테고리의 다른 글

vim-scala plugin  (0) 2020.02.11
Akka를 알아보자  (0) 2020.01.28