Elixir GUIDES を普通に読む7
Elixir GUIDES を読んだメモ
14. モジュールの属性
アノテーションとしてのモジュール
- 例
defmodule MyServer do @vsn 2 end
@vsn
はモジュールのバージョンを示す属性ここでは2と設定している
Elixirにはいくつかの予約済み属性がある
@moduledoc
: モジュールのドキュメント@doc
: 関数やマクロのドキュメント@behaviour
: OTPまたはユーザー定義の動作の指定@before_compile
: モジュールがコンパイルされる前に呼び出されるフック
Math モジュールにドキュメントを追加してみる
defmodule Math do @moduledoc """ Provides math-related functions. ## Examples iex> Math.sum(1, 2) 3 """ @doc """ Calculates the sum of two numbers. """ def sum(a, b), do: a + b end
- ドキュメントを見てみる
iex(1)> h Math Math Provides math-related functions. ## Examples iex> Math.sum(1, 2) 3 iex(2)> h Math.sum def sum(a, b) Calculates the sum of two numbers.
定数として
- 値を見やすく、再利用したい場合にモジュール属性を使う
- 値はコンパイル時にのみ存在する
defmodule MyServer do @initial_state %{host: "127.0.0.1", port: 3456} IO.inspect @initial_state end
temporary storage として
- Elixir の Web サーバー構築などに用いる共通基盤
plug
がある - Plugライブラリを用いることで、独自のPlugを定義できる
defmodule MyPlug do use Plug.Builder plug :set_header plug :send_ok def set_header(conn, _opts) do put_resp_header(conn, "x-header", "set") end def send_ok(conn, _opts) do send_resp(conn, 200, "ok") end end IO.puts "Running MyPlug with Cowboy on http://localhost:4000" Plug.Adapters.Cowboy.http MyPlug, []
plug/1
マクロを用いて、WEB要求がある時に呼び出される関数を接続したplug/1
を呼び出すたびに、指定された引数を@plugs
属性に保存するcall/2
で、@plugsの中のすべてのPlugを順番に実行する
15.構造体
構造体の定義
- 構造体の定義は、defstructを使う
- フィールドの定義と、デフォルト値を与えている
- 構造体の名前はモジュール名となる
defmodule User do defstruct name: "John", age: 27 end
構造体へのアクセスと更新
iex(2)> %User{} %User{age: 27, name: "John"} iex(3)> john = %User{} %User{age: 27, name: "John"} iex(4)> john.name "John" iex(5)> jane = %{john | name: "Jane"} %User{age: 27, name: "Jane"} iex(6)> %{jane | oops: :field} ** (KeyError) key :oops not found in: %User{age: 27, name: "Jane"} (stdlib) :maps.update(:oops, :field, %User{age: 27, name: "Jane"}) (stdlib) erl_eval.erl:256: anonymous fn/2 in :erl_eval.expr/5 (stdlib) lists.erl:1263: :lists.foldl/3
(
|
)は更新構文, 新しいキーが構造体に追加されることはない構造体はマップ
__struct__
で構造体の名前が取れる
iex(12)> is_map(john) true iex(13)> john.__struct__ User
- ただ、構造体はマップに実装されるプロトコルはいずれも使用できない
- 構造体を列挙したりアクセスしたりすることはできない
iex(14)> john[:name] ** (UndefinedFunctionError) function User.fetch/2 is undefined (User does not implement the Access behaviour) User.fetch(%User{age: 27, name: "John"}, :name) (elixir) lib/access.ex:267: Access.get/3
- Mapモジュールの関数を用いることはできる
iex(14)> jane = Map.put(%User{}, :name, "Jane") %User{age: 27, name: "Jane"} iex(15)> Map.merge(jane, %User{name: "John"}) %User{age: 27, name: "John"} iex(16)> Map.keys(jane) [:__struct__, :age, :name]