E221: Recurse With Default — 재귀 호출에서 기본 인자를 쓰면 위험해요

E221: Recurse With Default — 재귀 호출에서 기본 인자를 쓰면 위험해요

재귀 호출에서 어떤 파라미터에 기본 인자를 사용하면 이 경고가 발생해요. 기본값은 매번 호출할 때마다 현재 값을 스택 아래로 넘기는 대신 그대로 대입되기 때문에, 의도하지 않은 동작이 나올 수 있어요. 현재 파라미터 값을 넘기려던 걸 잘못해서 기본값에 의존한 것 같은 잠재적 버그를 잡아주는 경고입니다.

이 경고는 -Wrecurse-with-default 컴파일러 플래그로 켭니다.

출처: Scala 3 Reference

본문

Example

//> using options -Wrecurse-with-default

def fun(x: Int)(using p: Int, q: Int = 0): Int =
  if x <= 0 then p * q
  else fun(x - 1)(using p = p + x)

재귀 호출에서 q를 넘기지 않고 기본 인자에 맡겼어요.

Error

-- [E221] Type Warning: example.scala:5:17 -------------------------------------
5 |  else fun(x - 1)(using p = p + x)
  |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |       Recursive call used a default argument for parameter q.
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | It's more explicit to pass current or modified arguments in a recursion.
   -----------------------------------------------------------------------------

Solution

재귀 호출에서 모든 인자를 명시적으로 넘기세요.

//> using options -Wrecurse-with-default

def fun(x: Int)(using p: Int, q: Int = 0): Int =
  if x <= 0 then p * q
  else fun(x - 1)(using p = p + x, q = q)

아니면 아예 재귀 함수에서 기본 인자를 쓰지 않는 설계로 바꾸는 것도 방법이에요.

//> using options -Wrecurse-with-default

def fun(x: Int)(using p: Int)(q: Int): Int =
  if x <= 0 then p * q
  else fun(x - 1)(using p = p + x)(q)