E217: Erased Not Pure — erased 파라미터에는 순수 표현만 넣을 수 있어요

E217: Erased Not Pure — erased 파라미터에는 순수 표현만 넣을 수 있어요

erased 파라미터에 전달하는 인자나 erased 값의 오른쪽(RHS)이 순수 표현(pure expression)이 아니면 이 에러가 발생해요. erased 정의는 컴파일 타임에는 존재하지만 런타임에는 완전히 사라지는 값입니다. 값이 런타임에 남지 않으니, 전달되는 인자 역시 부수 효과가 없고 종료가 보장되는 "순수 표현"이어야 해요.

출처: Scala 3 Reference

본문

순수 표현이란 부수 효과(side effect)가 분명히 없고 종료가 보장되는 표현을 말해요. 대표적으로는 이런 것들이 있습니다.

  • 리터럴(literals)
  • 값에 대한 참조(references to values)
  • 부수 효과 없는 인스턴스 생성
  • 순수한 인자에 대한 인라인 함수 적용

Example

import scala.language.experimental.erasedDefinitions

def foo(erased a: Int): Int = 42

def example: Int =
  foo(println("side effect").asInstanceOf[Int])

여기서 println은 부수 효과를 일으키는 표현이라서 지금은 순수 표현으로 분류되지 않아요.

Error

-- [E217] Type Error: example.scala:6:41 ---------------------------------------
6 |  foo(println("side effect").asInstanceOf[Int])
  |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |      argument to an erased parameter fails to be a pure expression
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | The argument to an erased parameter must be a pure expression, but I found:
  |
  |   println("side effect").asInstanceOf[Int]
  |
  | This expression is not classified to be pure.
  | A pure expression is an expression that is clearly side-effect free and terminating.
  |           |Some examples of pure expressions are:
  |           |  - literals,
  |           |  - references to values,
  |           |  - side-effect-free instance creations,
  |           |  - applications of inline functions to pure arguments.
   -----------------------------------------------------------------------------

Solution

erased 파라미터의 인자로 순수 표현을 사용하면 됩니다. 리터럴을 쓰거나:

import scala.language.experimental.erasedDefinitions

def foo(erased a: Int): Int = 42

def example: Int =
  foo(0)  // literal is a pure expression

값에 대한 참조를 써도 돼요.

import scala.language.experimental.erasedDefinitions

def foo(erased a: Int): Int = 42

def example: Int =
  val pureValue = 123
  foo(pureValue)  // reference to a value is pure