LoginSignup
8
3

More than 3 years have passed since last update.

Elixirで構造体のプロパティを一部共通化する

Last updated at Posted at 2020-05-09

概要

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ライフを:thumbsup:

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3