13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ElixirAdvent Calendar 2022

Day 8

今日のElixirSchoolメモ8「モジュール」

Posted at

Elixir Schoolの学習メモです。

モジュールと名前つき関数

defmodule Example do # <- モジュール
  def greeting(name) do # <- 名前付き関数 
    "Hello #{name}."
  end
end

Example.greeting "Sean"
"Hello Sean."

モジュールは関数群を名前空間へと組織する最良の方法です。
関数をまとめることに加えて、関数のレッスンで取り上げた名前付き関数やプライベート関数を定義できます。

※名前空間(namespace)とは、名前の集合全体を小さな空間に区切り、それぞれに異なる識別名を与えることで、その空間内では他の空間に含まれる名前の競合・衝突を意識しなくて良いようにしたものです。
 プログラミング言語だと頻出する概念で、名前付き関数をモジュールにまとめて構造化できる、と捉えてもらうといいかも。

モジュールの属性

Elixirモジュールはそれぞれ対応するメタデータを持っている。メタデータの各項目のことをモジュールの属性といい、名前によって識別される。
モジュールの内部では、@記号を名前の前につけて属性につけて、属性にアクセスすることができる。

defmodule Example do
  @greeting "Hello"

  def greeting(name) do
    ~s(#{@greeting} #{name}.)
  end
end

Elixirで予約されている属性があり、一般的なのは以下の3つ。

moduledoc … 現在のモジュールにドキュメントをつける。
doc … 関数やマクロについてのドキュメント管理。
behaiviour … OTPまたはユーザが定義した振る舞い(ビヘイビア)に用いる。

構造体

構造体は、定義済みのキーの一群とデフォルト値を持つ特殊なマップをラップしたモジュール。
構造体を定義するにはdefstructを用い、フィールドとデフォルト値のキーワードリストを添える。

defmodule Subscriber do
  defstruct name: "", paid: false, over_18: true
end

iex(2)> s1 = %Subscriber{}
%Subscriber{name: "", over_18: true, paid: false}
iex(3)> s2 = %Subscriber{ name: "Dave" }
%Subscriber{name: "Dave", over_18: true, paid: false}

構造体のフィールドへのアクセス

iex(4)> s2.name
"Dave"

構造体の更新

iex(7)> s2 = %Subscriber{ s2 | name: "Tom" }
%Subscriber{name: "Tom", over_18: true, paid: false}
iex(8)> s2
%Subscriber{name: "Tom", over_18: true, paid: false}

構造体はマップに対してマッチすることができる。

iex(11)> %{name: "Tom"} = s2
%Subscriber{name: "Tom", over_18: true, paid: false}

Elixir 1.8以降、構造体にカスタムイントロスペクション機能が追加された。

iex(12)> inspect(s2)
"%Subscriber{name: \"Tom\", over_18: true, paid: false}"

@deriveで出力対象を指定できる。

defmodule Subscriber do
  @derive {Inspect, only: [:name]}
  # もしくはexceptで定義できる
  # @derive {Inspect, except: [:paid, :over_18]}

  defstruct name: "", paid: false, over_18: true
end

iex(15)> inspect(s2)
"#Subscriber<name: \"Tom\", ...>"

モジュールや構造体の取り扱いを簡単にするディレクティブ

  • aliasディレクティブ
  • importディレクティブ
  • requireディレクティブ
  • useマクロ

alias

モジュール名をエイリアスすることができる。

import

関数を取り込みたい場合に使う。

require

モジュールで定義したマクロを使うときは、そのモジュールをrequireする。
コードをコンパイルするときに、マクロ定義が有効になっていることが保証される。

use

他のモジュールを利用して現在のモジュールの定義を変更することができる。

13
0
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
13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?