どうも、靖宗です。
今回はモジュールの属性?モジュールを組み立てていくときに必要な情報っぽいです。
Module attributesというのはElixirで
意味不明な単語が最後に出てきましたが、順に見ていきましょう。
注釈として
Erlang由来の機能?モジュールにバージョンとかを記載できる。
defmodule MyServer do @vsn 2 end
@vsn
というのがバージョンを示す属性なんだそうで。VMでアップデートが必要かどうかの判断に使われるとのこと。
これも実際使われてるコードを見ないことにはピンときませんね。
よく使う属性を書いてくれてます。
@moduledoc
モジュールのドキュメント@doc
関数やマクロのドキュメント@behaviour
OTPの詳細?OTPがなんなのかわかんないんでよくわからん。たぶん振る舞い(適当)@before_compile
コンパイルされる前に発動するhook?('ω')。o(hook????????????)
@moduledoc
や@doc
はしょっちゅう使うみたい。というか使えと。
可読性が下がらない程度にはドキュメントは書いた方が良さげ。
以前書いたmath.ex
を改良する。
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
Markdownが使えるあたり、ドキュメントを生成するなにがしかがありそう。
一応、上の奴をコンパイルしてiex上で見てみる。h モジュール(関数)
で見れる。
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.
ExDoc
って奴を使うとHTMLでドキュメントが出力できる。
Markdownで書かれている旨みがこういう所ででてくるんですね。
"constants"として
Elixirの開発者はよくモジュールの属性を定数として使うそうです。
defmodule MyServer do @initial_state %{host: "127.0.0.1", port: 3456} IO.inspect @initial_state end
なるほど。
値を付けてない定数も書けるには書けるが警告が出る模様。
defmodule MyServer do @unknown end warning: undefined module attribute @unknown, please remove access to @unknown or explicitly set it before access
使う事は無さそう?
属性は内部の関数でも読むことができる。
defmodule MyServer do @my_data 14 def first_data, do: @my_data @my_data 13 def second_data, do: @my_data end MyServer.first_data #=> 14 MyServer.second_data #=> 13
モジュール内で何回も定義するのはなんかおかしい気もしますが、上記のコードはコメントの通りになるそうです。
ただ、この定数はコンパイル時に保持しているだけで実行の際に参照されている訳では無さそう。つまり、上記のコードはコンパイルされれば
defmodule MyServer do def first_data, do: 14 def second_data, do: 13 end
となっている筈。
あと、属性を定義するときは属性名とその値の間に改行はいれたらダメだそうです。
一時的なストレージとして
ElixirのWebフレームワーク?の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(conn, 200, "ok") end end IO.puts "Running MyPlug with Cowboy on http://localhost:4000" Plug.Adapters.Cowboy.http MyPlug, []
ここでplug/1
というマクロはウェブリクエストがあったときに関数とつなげるマクロだそうです。
('ω')。o(????????????)
全然意味が分からない・・・
コンパイル直前にPlug
の内部にあるcall/2
という関数が実行される?
メタプログラミング的な処理なんでしょうか、イマイチよくわかりません。
もうここではおまじない程度に考えておいた方が良さそうです。戦略的後回し!
以前に出てきたExUnit
の例も出てきてたので一応記載。
defmodule MyTest do use ExUnit.Case @tag :external test "contacts external service" do # ... end end
これを見るとやはり@tag
というのがコンパイル時になにがしかの関数に変換され動作する気がするんですよね。
なにやら「メタプログラミングの項目見てくれ」的な事も書いてますし、ここでは深追いしない方が良さげです。