시청

시청

학습 연습 문제

소개

문서

Elixir에서는 문서를 일급 시민으로 대접해요.

코드를 문서화할 때 흔히 쓰는 모듈 속성이 두 개 있어요. 모듈을 문서화하는 @moduledoc과, 바로 뒤에 오는 함수를 문서화하는 @doc이에요. @moduledoc 속성은 보통 모듈의 첫 줄에 오고, @doc 속성은 보통 함수 정의 바로 앞에 오는데, 함수에 타입스펙이 있다면 그 타입스펙 바로 앞에 와요. 문서는 보통 히어독 문법을 사용한 여러 줄 문자열로 작성해요.

Elixir 문서는 Markdown으로 작성해요.

defmodule String do
  @moduledoc """
  Strings in Elixir are UTF-8 encoded binaries.
  """

  @doc """
  Converts all characters in the given string to uppercase according to `mode`.

  ## Examples

      iex> String.upcase("abcd")
      "ABCD"

      iex> String.upcase("olá")
      "OLÁ"
  """
  def upcase(string, mode \\ :default)
end

타입스펙

Elixir는 동적으로 타입이 정해지는 언어라서 컴파일 시점의 타입 검사를 제공하지 않아요. 그래도 타입스펙은 문서의 한 형태로 사용할 수 있어요.

타입스펙은 @spec 모듈 속성을 함수 정의 바로 앞에 두어 추가할 수 있어요. @spec 뒤에는 함수 이름과, 괄호 안에 쉼표로 구분한 모든 인자의 타입 목록이 와요. 반환값의 타입은 함수의 인자와 이중 콜론 ::으로 구분해요.

@spec longer_than?(String.t(), non_neg_integer()) :: boolean()
def longer_than?(string, length), do: String.length(string) > length

타입

가장 흔히 쓰는 타입은 다음과 같아요:

  • 불리언: boolean()
  • 문자열: String.t()
  • 숫자: integer(), non_neg_integer(), pos_integer(), float()
  • 배열: list()
  • 모든 타입의 값: any()

일부 타입은 매개변수화할 수 있어요. 예를 들어 list(integer)는 정수 배열이에요.

리터럴 값도 타입으로 사용할 수 있어요.

타입의 합집합은 파이프 |로 나타낼 수 있어요. 예를 들어 integer() | :error는 정수이거나 아톰 리터럴 :error라는 뜻이에요.

모든 타입의 전체 목록은 공식 문서의 "Typespecs" 섹션에서 볼 수 있어요.

인자 이름 짓기

타입스펙의 인자에는 이름을 붙일 수도 있는데, 같은 타입의 인자가 여러 개일 때 구분하기 좋아요. 인자 이름 뒤에 이중 콜론을 붙여서 인자의 타입 앞에 써요.

@spec to_hex({hue :: integer, saturation :: integer, lightness :: integer}) :: String.t()

사용자 정의 타입

타입스펙은 내장 타입에만 국한되지 않아요. @type 모듈 속성으로 사용자 정의 타입을 만들 수 있어요. 사용자 정의 타입 정의는 타입의 이름으로 시작하고, 그 뒤에 이중 콜론, 그리고 타입 자체가 와요.

@type color :: {hue :: integer, saturation :: integer, lightness :: integer}

@spec to_hex(color()) :: String.t()

사용자 정의 타입은 정의한 모듈 안에서도, 다른 모듈에서도 사용할 수 있어요.

지침

시청에서 한동안 일하면서, 서류를 작성할 때처럼 일상적인 업무를 빠르게 처리해 주는 도구들을 만들어 왔어요.

그런데 새 동료가 합류하게 되었고, 문득 도구가 그다지 직관적이지 않을 수도 있겠다는 생각이 들었어요. 사무실에는 서류는 항상 대문자로 작성하기, 빈칸은 남기지 않기 같은 이상한 관례가 많거든요.

그래서 새 동료가 곧바로 적응해 도구를 사용할 수 있도록 문서를 좀 써 두기로 했어요.

1. 서식 도구의 목적 문서화하기

Form 모듈에 그 목적을 설명하는 문서를 추가해요. 내용은 다음과 같아요:

A collection of loosely related functions helpful for filling out various forms at the city office.

2. 빈 값으로 필드를 채우는 함수 문서화하기

Form.blanks/1 함수에 문서와 타입스펙을 추가해요. 문서 내용은 다음과 같아요:

Generates a string of a given length.

This string can be used to fill out a form field that is supposed to have no value.
Such fields cannot be left empty because a malicious third party could fill them out with false data.

타입스펙은 이 함수가 음이 아닌 정수 하나를 인자로 받고 문자열을 반환한다는 것을 설명해야 해요.

3. 값을 대문자 배열로 나누는 함수 문서화하기

Form.letters/1 함수에 문서와 타입스펙을 추가해요. 문서 내용은 다음과 같아요:

Splits the string into a list of uppercase letters.

This is needed for form fields that don't offer a single input for the whole string,
but instead require splitting the string into a predefined number of single-letter inputs.

타입스펙은 이 함수가 문자열 하나를 인자로 받고 문자열 배열을 반환한다는 것을 설명해야 해요.

4. 값이 최대 길이의 필드에 맞는지 확인하는 함수 문서화하기

Form.check_length/2 함수에 문서와 타입스펙을 추가해요. 문서 내용은 다음과 같아요:

Checks if the value has no more than the maximum allowed number of letters.

This is needed to check that the values of fields do not exceed the maximum allowed length.
It also tells you by how much the value exceeds the maximum.

타입스펙은 이 함수가 문자열과 음이 아닌 정수, 두 개의 인자를 받고 두 가지 값 중 하나를 반환한다는 것을 설명해야 해요. :ok 아톰을 반환하거나, 첫 번째 원소가 :error 아톰이고 두 번째 원소가 양의 정수인 2-튜플을 반환해요.

5. 서로 다른 주소 형식 문서화하기

알 수 없는 이유에서인지, 시청 내부 시스템은 주소를 나타내는 방식으로 맵과 튜플, 두 가지를 사용해요.

이 사실을 세 개의 사용자 정의 공개 타입을 정의해서 문서화해요:

  • address_map - :street, :postal_code, :city 키를 가진 맵이에요. 각 키는 문자열 타입의 값을 담아요.
  • address_tuple - street, postal_code, city 세 값을 가진 튜플이에요. 각 값은 문자열 타입이고, 타입스펙에서 이름을 붙여 값들을 서로 구분해요.
  • address - address_map 또는 address_tuple이 될 수 있어요.

6. 주소 포맷팅 문서화하기

Form.format_address/1 함수에 문서와 타입스펙을 추가해요. 문서 내용은 다음과 같아요:

Formats the address as an uppercase multiline string.

타입스펙은 이 함수가 주소 하나를 인자로 받고 문자열을 반환한다는 것을 설명해야 해요.

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

시청 문제를 시작해 볼 준비가 됐나요?

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