Elixir School 2日目
はじめに
- 前回の続き
- 今回もiexをベースに基礎編のインプット・アウトプットをする
モジュールについて
モジュール
- classみたいな感じで、複数の関数などを束ねることが可能
defmodule
で定義することが可能。またmoduleはネストすることも可能である。
構造体
- データクラスみたいな感じ
defstruct
で定義する
iex(1)> defmodule Example.User do ...(1)> defstruct id: 1, last_name: "", family_name: "", roles: [] ...(1)> end {:module, Example.User, <<70, 79, 82, 49, 0, 0, 6, 220, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 189, 0, 0, 0, 18, 19, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108, 101, 46, 85, 115, 101, 114, 8, 95, 95, ...>>, %Example.User{family_name: "", id: 1, last_name: "", roles: []}} iex(2)> user = %Example.User{last_name: "Steve"} %Example.User{family_name: "", id: 1, last_name: "Steve", roles: []} iex(3)> user = %{user | family_name: "John"} %Example.User{family_name: "John", id: 1, last_name: "Steve", roles: []}
コンポジション
alias
module
に対してalias
を貼ることが可能- ネストしてる
module
はalias貼った方が可読性があがる。 - 命名が衝突してなければ、
alias XXX.YYYY
でYYYYに対してアクセスできるようになるし、衝突するもしくは任意の名前に変更したい場合はalias XXX.YYYY, as: ZZZZZ
みたいなことが可能 - 一度に複数のモジュールに対してalias貼ることも
alias XXX.{YYYY, ZZZZ}
みたいな感じで可能
import
- モジュールをエイリアスするよりも、関数を取り込みたいという場合には、 import を使う
- importは全ての関数およびマクロをimportするので、
:only
やexcept
で絞ることが可能 。import List, only: [last: 1]
mix
mix new
を叩くことで、プロジェクトのフォルダ構成と必要なボイラープレート(決まりきったソースコード断片)が生成される- package managerみたいな役割を果たしてくれる
ドキュメントの作成
#
使うか@doc
使うか@moduledoc
使うかという話。- あんまりdocを書かない人間なので割愛
テスト
- Elixirに組み込まれているテストフレームワークはExUnitという
- テストを走らせる前にExUnitを
ExUnit.start()
で開始する必要があり、これは通常test/test_helper.exs
内で行われる - 雑に
mix new
で作成したプロジェクトの中で引数を足し算する実装とテストを作成してみる
defmodule ElixirSchool do def hello do :world end def add(args1, args2) do args1 + args2 end end
defmodule ElixirSchoolTest do use ExUnit.Case doctest ElixirSchool test "add" do assert ElixirSchool.add(1, 2) == 3 end end
assert
は他の言語のテストでもおなじみの感じで、refute
とassert_raise
,assert_receive
がある- テストのセットアップは
setup
とsetup_all
マクロを使うことができる。setup
は各テストの前、setup_all
は全体のテストの前に一度だけ実行される。どちらも {:ok, state} のタプルを返すことが期待されていて、stateはテスト内で利用可能。 - モックについては下記の通りらしい
Elixirでのモックに対する単純な解答は、使うな、です。本能のままにモックへと手を伸ばしているかもしれませんが、Elixirのコミュニティや正当な理由からはとても推奨されていないものです。
内包表記
- for文でコレクションなどを操作することができる
- 回せるものはリストに限らない
- あくまでも syntax sugarなので必要なときのみにした方がいいというスタンスのよう
iex(1)> for x <- 1..5, do: x*x [1, 4, 9, 16, 25] # キーワードリスト iex> for {_key, val} <- [one: 1, two: 2, three: 3], do: val [1, 2, 3] # マップ iex> for {k, v} <- %{"a" => "A", "b" => "B"}, do: {k, v} [{"a", "A"}, {"b", "B"}] # バイナリ iex> for <<c <- "hello">>, do: <<c>> ["h", "e", "l", "l", "o"]
フィルタ
- フィルタは内包表記のためのある種のガードと考えることができる
- false, nilの場合は取り除くことが可能
import Integer iex> for x <- 1..10, is_even(x), do: x [2, 4, 6, 8, 10]
おまけ
- 基礎編最後に個人的にFizzbuzzをやってみる
defmodule ElixirSchool do def fizzbuzz(args) do cond do rem(args, 15) == 0 -> "fizzbuzz" rem(args, 3) == 0 -> "fizz" rem(args, 5) == 0 -> "buzz" true -> nil end end end
defmodule ElixirSchoolTest do use ExUnit.Case doctest ElixirSchool test "fizzbuzz" do assert ElixirSchool.fizzbuzz(15) == "fizzbuzz" end test "fizz" do assert ElixirSchool.fizzbuzz(3) == "fizz" end test "buzz" do assert ElixirSchool.fizzbuzz(5) == "buzz" end test "nul" do assert ElixirSchool.fizzbuzz(4) == nil end end
こんな感じ。
- ElixirSchoolの基礎編をやりきってfizzbuzzするのに半日くらいしかかからなかったので、結構楽しかったです。
- 次回からElixirSchoolの応用編をやってみる