Elixir入門
拡張子
.ex - アプリケーションコードはこっち. 最終的にバイトコードにコンパイルして実行します
.exs - テストコードやスクリプトはこっち
実行方法
$ elixir file.exs
code:sh
$ iex
iex(1)> c file.exs
ビルドツール
条件分岐
ピン演算子
変数の現在の値をパターンマッチのパターンとして使います
code:elixir
a = 100
^a = 100 # => 👌OK
^a = 200 # => 🙅NG
key = "name"
%{ ^key => name } = %{ "name" => "hoge" } # => 👌OK (%{"name" => "hoge"})
データ構造
タプル
code:elixir
{ 1, 2 }
{ :ok, "hello" }
リスト
code:elixir
# 空リスト
[]
# パターンマッチ
a # => 10
b # => 20
c # => 30
head # => 1
# 連結
# 要素の確認
# Listモジュール
List.foldl(10, 20, 30, 0, fn x, sum -> sum + x end) # => 60 List.keyreplace({:foo, 1}, {:bar, 2}, {:baz, 3}, 2, 1, {:hoge, 20}) # => foo: 1, hoge: 20, baz: 3 キーワードリスト
code:elixir
# 記法
# 最後の引数がキーワードリストの場合、ブラケットを省略できる
do_something arg, opt1: 1, opt2: "hello" # do_something arg, [opt1: 1, opt2: "hello"]と同義
# Keywordモジュール
マップ
code:elixir
map = %{ name: "piyo", age: 10 }
map = %{ map | name: "hoge" } # => %{age: 10, name: "hoge"}
# パターンマッチ
%{ name: a_name } = %{ name: "hoge", age: 30 } # => %{age: 30, name: "hoge"}
a_name # => "hoge"
%{ name: _, age: _ } = %{ name: "hoge", age: 24 } # => %{age: 24, name: "hoge"}
%{ name: a_name } = %{ a: 1 } # => 🙅NG
%{ name: "hoge" } = %{ name: "hoge", age: 30 } # => OK
%{ name: "piyo" } = %{ name: "hoge", age: 30 } # => 🙅NG
# Mapモジュール
Map.values %{ first_name: "hoge", last_name: "fuga" } # => "hoge", "piyo" Map.put %{ name: "hoge" }, :likes, "Elixir" # => %{likes: "Elixir", name: "hoge"}
Map.has_key? %{ first_name: "hoge" }, :last_name # => false
Map.pop %{ name: "piyo", likes: "Deno" }, :likes # => {"Deno", %{name: "piyo"}}
Map.equal? %{ a: 1, b: 2 }, %{ a: 1, b: 2 } # => true
Map.put_new(%{ name: "hoge" }, :height, 180) # => %{height: 180, name: "hoge"}
セット
MapSetを使う
code:elixir
set = Enum.into(1..10, MapSet.new) # => #MapSet<1, 2, 3, 4, 5, 6, 7, 8, 9, 10> MapSet.member? set, 4 # => true
構造体
モジュール名が構造体の名前として扱われます
code:elixir
defmodule User do
defstruct name: "", age: 15
def to_string(%User{name: name, age: age}) do
end
end
code:elixir
%User{} # => %User{age: 15, name: ""}
%User{ name: "hoge" } # => %User{age: 15, name: "hoge"}
%User{ name: "hoge", no_such_key: true } # => 🙅NG (KeyError)
# フィールドへのアクセス
user = %User{}
user.age # => 15
# パターンマッチ
%User{ name: user_name } = user
user_name # => ""
# 更新
user = %User{ user | name: "piyo" } # => %User{age: 15, name: "piyo"}
User.to_string(user) # => "name: , age: 15"
コレクションの処理
code:elixir
ストリーム
code:elixir
# Enumモジュールの関数にストリームを渡すと結果を得られる
# Stream.cycle => 列挙可能なデータから無限ストリームを生成する。最後の要素まで到達したら、最初の要素に戻る
# Stream.repeatedly
Stream.repeatedly(fn -> 1 end) |> Enum.take(3) # => 1, 1, 1 # Stream.iterate
Stream.iterate(0, &(&1 + 1)) |> Enum.take(4) # => 0, 1, 2, 3 内包表記
code:elixir
for x <- 1,2,3,4,5, y <- 1,2,3,4,5, x > y, do: x*y # => 2, 3, 6, 4, 8, 12, 5, 10, 15, 20 モジュール
code:elixir
defmodule SomeModule do
# パブリック関数
# @example SomeModule.greet "taro"
def greet(name) do
message = make_message(name)
IO.puts(message)
end
# プライベート関数
defp make_message(name) do
end
end
シジル(Sigil)
正規表現(~r{...})等の~から始まる文法のこと
文字列と文字のリスト
Elixirでは"..."で囲まれたものを文字列、'...'で囲まれたものを文字のリストとして扱います 文字のリスト('...')は実体としては整数のリスト
code:elixir
is_list 'hello' # => true
is_list "hello" # => false
バイナリ
code:elixir
binary = << 1, 2, 3, 4 >>
byte_size binary # => 4
bit_size binary # => 32
# ビット数の指定
bit_size << 1::size(2) >> # => 2
byte_size << 1::size(2) >> # => 1
bit_size << 1::size(8), 2::size(4) >> # => 12
byte_size << 1::size(8), 2::size(4) >> # => 2
プロセス
参考