트랙
/
Elixir
Elixir
/
연습 문제
/
스택 언더플로
스택 언더플로

스택 언더플로

학습 연습 문제

소개

예외

Elixir의 모든 오류는 _Exception Behaviour_를 구현해요. _Access Behaviour_와 마찬가지로, _Exception Behaviour_는 behaviour의 소프트웨어 계약을 충족하기 위해 모듈이 반드시 구현해야 하는 콜백 함수를 정의해요. 오류를 한 번 정의하면 다음과 같은 속성을 가져요.

  • 모듈의 이름이 오류의 이름을 정의해요.
  • 모듈이 오류 구조체를 정의해요.
  • 구조체에는 :message 필드가 있어요.
  • 모듈을 raise/1과 raise/2와 함께 사용해서 의도한 오류를 발생시킬 수 있어요.

_Exception Behaviour_는 message/1과 exception/1이라는 두 가지 콜백도 지정해요. 구현하지 않으면 기본 구현이 사용돼요. message/1은 raise와 함께 호출되면 오류 구조체를 읽기 쉬운 메시지로 변환해요. exception/1은 raise/2와 함께 호출되면 메시지에 추가적인 맥락을 더할 수 있게 해줘요.

예외 정의하기

오류 모듈에서 예외를 정의하려면 defexception 매크로를 사용해요.

# Defines a minimal error, with the name `MyError`
defmodule MyError do
  defexception message: "error"
end

# Defines an error with a customized exception/1 function
defmodule MyCustomizedError do
  defexception message: "custom error"

  @impl true
  def exception(value) do
    case value do
      [] ->
        %MyCustomizedError{}

      _ ->
        %MyCustomizedError{message: "Alert: " <> value}
    end
  end
end

예외 사용하기

정의한 오류는 raise/1이나 raise/2를 사용해서 내장 오류처럼 사용할 수 있어요.

  • raise/1은 모듈 이름으로 특정 오류를 발생시켜요. 인자가 문자열이면 그 문자열을 메시지로 하는 RuntimeError를 발생시켜요.
  • raise/2는 모듈 이름으로 특정 오류를 발생시키고, 속성 인자를 받아서 그 인자로 적절한 메시지를 가진 오류를 얻어요.

지침

_Instruments of Texas_에서 일하는 동안, RPN 계산기의 Elixir 구현에 진전이 있었어요. 팀은 표준 라이브러리가 제공하는 일반적인 오류보다 더 구체적인 오류를 발생시킬 수 있기를 바라고 있어요. 지금은 조사를 좀 하고 있지만, _Exception Behaviour_를 구현하는 두 가지 새로운 오류를 만들기로 결정했어요.

1. 0으로 나누기 오류

숫자를 0으로 나누면 정의되지 않은 결과가 나오는데, 팀은 이를 오류로 나타내는 것이 가장 좋다고 판단했어요.

오류 메시지가 "division by zero occurred"가 되도록 DivisionByZeroError 모듈을 구현해요.

raise DivisionByZeroError
# => ** (DivisionByZeroError) division by zero occurred

2. 스택 언더플로가 발생했을 때의 오류

RPN 계산기는 숫자들이 더해지기 전에 이들을 추적하기 위해 _스택_을 사용해요. 팀은 이 _스택_을 숫자(정수와 실수)의 배열로 표현하는데, 예를 들어 [3, 4.0]과 같아요. 각 연산은 계산을 수행하기 위해 스택에 특정 개수의 숫자가 있어야 해요. 스택에 숫자가 충분하지 않을 때, 이를 스택 언더플로 오류라고 해요. 기본 메시지와 선택적인 추가 컨텍스트를 제공하는 StackUnderflowError 예외를 구현해요.

raise StackUnderflowError
# => ** (StackUnderflowError) stack underflow occurred

raise StackUnderflowError, "when dividing"
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing

3. 나누기 함수 작성하기

스택 (숫자 두 개의 배열) 을 받아 다음과 같이 동작하는 divide/1 함수를 구현해요.

  • 스택에 숫자가 충분하지 않으면 스택 언더플로 오류를 발생시켜요
  • 제수가 0이면 0으로 나누기 오류를 발생시켜요 (숫자 스택은 역순으로 저장된다는 점에 주의해요)
  • 오류가 발생하지 않으면 나눗셈을 수행해요
RPNCalculator.Exception.divide([])
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing

RPNCalculator.Exception.divide([0, 100])
# => ** (DivisionByZeroError) division by zero occurred

RPNCalculator.Exception.divide([4, 16])
# => 4

배열의 순서는 뒤집혀 있다는 점에 주의해요!

GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Elixir Exercism

스택 언더플로 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Elixir 트랙을 개념 58개연습 문제 168개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.