Elixir에서 구조체의 속성을 부분적으로 공통화

개요



Elixir에서 구조체의 속성을 공통화하고 싶었기 때문에 메모도 함께 공유합니다.

환경


$ elixir -v
Erlang/OTP 22 [erts-10.7.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

Elixir 1.10.3 (compiled with Erlang/OTP 22)

코드



common_struct.ex

# 共通プロパティを持ち、`use`によって構造体を定義するモジュール
defmodule CommonStruct do
  defmacro __using__(attributes) do
    quote do
      # 共通プロパティ
      common_attributes = [str: "", int: 0]

      # 引数のキーワードリストと一緒に`defstruct`へ渡し、呼び出しモジュールの構造体として定義する。
      common_attributes ++ unquote(attributes) |> defstruct
    end
  end
end

my_struct.ex
defmodule MyStruct do
  # 独自に定義するプロパティとデフォルト値をキーワードリストにして渡す。
  use CommonStruct, bool: false, float: 0.1
end

iex
iex(1)> i %MyStruct{}
Term
  # ちゃんと定義できてます!
  %MyStruct{bool: false, float: 0.1, int: 0, str: ""}
Data type
  MyStruct
Description
  This is a struct. Structs are maps with a __struct__ key.
Reference modules
  MyStruct, Map
Implemented protocols
  IEx.Info, Inspect

# デフォルト値
iex(2)> %MyStruct{}
%MyStruct{bool: false, float: 0.1, int: 0, str: ""}

# 初期値あり
iex(3)> %MyStruct{bool: true, float: 3.14, int: 100, str: "hoge"}
%MyStruct{bool: true, float: 3.14, int: 100, str: "hoge"}
CommonStruct 에는 구조체가 정의되어 있지 않으므로 위 코드에서 %CommonStruct{} 를 실행하면 오류가 발생합니다.

iex
iex(4)> %CommonStruct{}
** (CompileError) iex:4: CommonStruct.__struct__/1 is undefined, cannot expand struct CommonStruct. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code

공통 부분도 구조체로 하고 싶은 경우는, 아래와 같이 하면 할 수 있습니다.

common_struct.ex
defmodule CommonStruct do
  defmacro __using__(attributes) do
    quote do
      CommonStruct.common_attributes() ++ unquote(attributes) |> defstruct
    end
  end

  # defstruct, __using__で利用するためにモジュール変数に追い出す
  @common_attributes [str: "", int: 0]
  defstruct @common_attributes
  def common_attributes(), do: @common_attributes
end

iex
iex(1)> i %CommonStruct{}
Term
  %CommonStruct{int: 0, str: ""}
Data type
  CommonStruct
Description
  This is a struct. Structs are maps with a __struct__ key.
Reference modules
  CommonStruct, Map
Implemented protocols
  IEx.Info, Inspect

이상입니다!

여러분이 좋아하는 Elixir 생활을

좋은 웹페이지 즐겨찾기