構造体

cf. 15 構造体 – Structs – Elixir

構造体はマップの拡張だ。初期値、コンパイル時の保証、多態をもたらす、って書いてある。多態ってのはどういう意味だ?それから初期値があるのもなんだかなぁという気がする。
まあ、いい。例を見てみよう。構造体を定義するには、モジュールの中で defstruct/1 を使う。

defmodule User do

  defstruct name: "john", age: 27

end
^o^ > iex struct.exs
Eshell V8.0  (abort with ^G)
Interactive Elixir (1.3.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> %User{}
%User{age: 27, name: "john"}
iex(2)> %User{name: "meg"}
%User{age: 27, name: "meg"}
iex(3)> is_map(%User{})
true

構造体は、用意しているフィールドが存在することをコンパイル時に保証する。逆に言うと、用意していないフィールドを使おうとするとエラーになる。

iex(4)> %User{oops: :field}
** (KeyError) key :oops not found in: %User{age: 27, name: "john"}
    (stdlib) :maps.update(:oops, :field, %User{age: 27, name: "john"})
             struct.exs:3: anonymous fn/2 in User.__struct__/1
    (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
             expanding struct: User.__struct__/1
             iex:4: (file)

構造体はマップの拡張なので、マップと同様のアクセスができる。

iex(4)> john = %User{}
%User{age: 27, name: "john"}
iex(5)> john.name
"john"
iex(6)> meg = %{john | name: "meg"}
%User{age: 27, name: "meg"}
iex(7)> %{meg | oops: :field}
** (KeyError) key :oops not found in: %User{age: 27, name: "meg"}
    (stdlib) :maps.update(:oops, :field, %User{age: 27, name: "meg"})
    (stdlib) erl_eval.erl:255: anonymous fn/2 in :erl_eval.expr/5
    (stdlib) lists.erl:1263: :lists.foldl/3

パターンマッチングでもよく用いられる。

iex(7)> %User{name: name} = john
%User{age: 27, name: "john"}
iex(8)> name
"john"
iex(9)> %User{} = %{}
** (MatchError) no match of right hand side value: %{}

構造体はディクショナリではないので Dict モジュールからは使えない。

iex(9)> Dict.get(%User{}, :name)
** (UndefinedFunctionError) function User.get/3 is undefined or private
    User.get(%User{age: 27, name: "john"}, :name, nil)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください