var/val 매개변수는 call-by-name일 수 없음

var/val 매개변수는 call-by-name일 수 없음 (Var Val Parameters May Not Be Call By Name)

클래스나 트레이트의 val·var 매개변수를 call-by-name(=> T 문법)으로 선언했을 때 나오는 에러예요.

출처: Scala 3 Reference

본문

클래스나 트레이트의 val 또는 var 매개변수를 call-by-name(값 대신 => T 문법)으로 선언하면 이 에러가 발생해요.

클래스와 트레이트의 var·val 매개변수는 필드로 저장되어야 하기 때문에 call-by-name이 될 수 없어요. 매개변수를 필요할 때마다 평가하고 싶다면, 그냥 일반 매개변수로 두고 클래스 안에 def를 제공하는 방법을 고려해 보세요.

예시

class LazyHolder(val value: => Int)

에러 메시지

-- [E055] Syntax Error: example.scala:1:28 -------------------------------------
1 |class LazyHolder(val value: => Int)
  |                            ^^
  |                            val parameters may not be call-by-name
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | var and val parameters of classes and traits may no be call-by-name. In case you
  | want the parameter to be evaluated on demand, consider making it just a parameter
  | and a def in the class such as
  |   class MyClass(valueTick: => String) {
  |     def value() = valueTick
  |   }
   -----------------------------------------------------------------------------

해결 방법

// Use a regular parameter and a lazy val
class LazyHolder(valueInit: => Int):
  lazy val value: Int = valueInit
// Or use a function type
class LazyHolder(getValue: () => Int):
  def value: Int = getValue()
// Or simply use a regular val parameter
class LazyHolder(val value: Int)

더 알아보기

  • 값을 지연 평가하고 싶다면 일반 매개변수를 받아 lazy val이나 def로 감싸면 돼요.