UndefinedFunctionError 예외

UndefinedFunctionError 예외

"그런 함수는 없는데요?" — 이 예외는 존재하지 않는 함수를 호출했을 때 던져져요. 미리 정의되지 않은 함수를 호출하거나, 외부 모듈에서 존재하지 않는 함수를 호출하면 마주치는 예외예요. 함수 이름이나 아리티(arity)를 잘못 적었을 때 흔히 발생하죠.

출처: UndefinedFunctionError exception (Elixir v1.20.4)

본문

UndefinedFunctionError는 정의되지 않은 함수를 호출했을 때 발생하는 예외예요.

예를 들어 아래 코드처럼 apply/3로 존재하지 않는 함수를 호출하면 이 예외를 만나요. (apply/3를 쓰는 이유는 그렇지 않으면 Elixir가 컴파일 타임 경고를 내기 때문이에요.)

# Let's use apply/3 as otherwise Elixir emits a compile-time warning
iex> apply(String, :non_existing_fun, ["hello"])
** (UndefinedFunctionError) function String.non_existing_fun/1 is undefined or private

이 예외는 다음과 같은 공개 필드를 가지며, 자유롭게 접근할 수 있어요.

  • :module (module/0) - 모듈 이름이에요.
  • :function (atom/0) - 함수 이름이에요.
  • :arity (non_neg_integer/0) - 함수의 아리티(인자 개수)예요.

오류 메시지를 보면 어떤 모듈의 어떤 함수가 몇 개 인자를 받는 형태로 호출됐는지가 그대로 드러나요. 위 예시에서는 String.non_existing_fun/1, 즉 String 모듈의 non_existing_fun을 1개 인자로 호출했다는 뜻이에요.

참고로 "undefined(정의되지 않음)"뿐 아니라 "private(비공개)"인 경우에도 이 예외가 발생해요. private 함수는 모듈 밖에서 호출할 수 없기 때문에, 외부에서 호출하면 마치 존재하지 않는 함수처럼 취급되는 거죠. 그래서 foo/1이 정의되지 않은 경우든, private으로 선언된 경우든 같은 예외가 던져져요.

이 예외를 만났을 때는 세 가지를 확인해 보세요. 첫째, 함수 이름의 철자가 맞는지. 둘째, 인자 개수(아리티)가 실제 정의와 맞는지. 셋째, 대상 모듈에 실제로 그 함수가 있는지, 그리고 있다면 public 함수인지. 이 셋을 점검하면 대부분의 원인을 찾을 수 있어요.

더 알아보기