概要
型や変数の命名規則、演算子、スコープなど、変数の基本的な知識を解説している章。
型
値型
整数
10, 16, 8 , 2 進数で表すことができる。10 進数では、数値の区切りに _
を使用できる。
決まった最大値はない。
浮動小数点数
小数点で表す。小数点の前後に少なくとも 1 つ数値を書かなければいけない。
指数も追記することができる 0.314e1
。 IEEE 754 倍精度(double) 16 桁程度の正確さを持つ。
アトム
コロン(:
)で始まる、名前を表現する定数。アルファベット, 数字, _
, @
を使用可能で、末尾に !
, ?
を使うことができる。ダブルクォートで囲むと任意の文字を使用できる。
:taro
, :is_taro?
, :"he is taro"
同じ値のアトムは比較すると必ず同じになる。
範囲
start..end
で表す。start, end は整数。
正規表現
~r{regexp}opts
のように表す。opts
はオプション指定する場合に書く(docs 参照)。
区切り文字には {}
以外でもアルファベット文字以外は使用できる //
など。ただし、//
を使用すると正規表現内に /
が含まれる場合エスケープする必要がある。
iex> Regex.match?(~r{taro}, "yamada taro")
=> true
iex> Regex.match?(~r{taro}i, "Yamada Taro")
=> true
システム型
PID・ポート
PID はローカル・リモートプロセスへの参照で、ポートは読み書きするリソースへの参照。
カレントプロセスの PID は self で取得ができ、新しい PID は新しいプロセスを生成した時に作られる。
リファレンス
make_ref
でグローバルに一意なリファレンスを生成する。
コレクション型
タプル
順序を持ったコレクション。{}
で囲む。
{:a, :b, :c}
{1, 2}
関数でエラーが無いときに、第一要素に :ok
というアトムを持つタプルを返すことをよくやる。
iex> {status, file} = File.open('log.txt')
=> {:ok, #PID<0.82.0>}
これを利用して、成功を仮定したマッチを書くのに使う
iex> {:ok, file} = File.open('no_exist.txt')
** (MatchError) no match of right hand side value: {:error, :enoent}
リスト
[1, 2, 3]
のように書く。
他言語での配列ではなく、連結データ構造になっており、一つの head(先頭要素)と一つの tail(それ以降)からなる。head は一つの値を持ち、tail はリストになっている。これは再帰的な処理を書く際の核となる。
また、幾つかリストのための演算子がある。
iex> [1, 2] ++ [3, 4, 5]
=> [1, 2, 3, 4, 5]
iex> [1, 2, 3] -- [3, 4, 5]
=> [1, 2]
iex> 1 in [1, 2, 3]
=> true
キーワードリスト
[a: 1, b: 2, c: 3]
のように、キーと値のペアのリストを書く事ができる。
一見 Ruby の Hash のように見えるが、Ruby の Hash に近いものは次に紹介するマップで表す。
キーワードリストは、内部で 2 つの要素を持つタプルのリストに変換され、[{:a, 1}, {:b, 2}, {:c, 3}]
と同じ意味である。
iex> [a: 1, b: 2, c: 3] === [{:a, 1}, {:b, 2}, {:c, 3}]
=> true
マップ
キーと値のペアのコレクション。以下の様に書く。
%{key => value, key => value}
キーは文字列、タプル、アトムと様々なものを使用することができる。
iex> %{'name' => 'taro'}
=> %{'name' => 'taro'}
iex> %{{'name', 'namae'} => 'taro'}
=> %{{'name', 'namae'} => 'taro'}
iex> %{:name => 'taro'}
=> %{name: 'taro'}
キーの型は異なって良い
iex> %{:name => 'taro', 'address' => 'Tokyo', {:tel, :fax} => '000-1111-2222' }
=> %{:name => 'taro', {:tel, :fax} => '000-1111-2222', 'address' => 'Tokyo'}
式も使うことができる
iex> %{String.downcase("NAME") <> "_1" => 'taro'}
%{"name_1" => 'taro'}
キーワードリストと違い、同じキーを許さない
iex> %{name: 1, name: 2}
=> %{name: 2}
一般的に、キーワードリストはコマンドラインパラメーターやオプションの受け渡し、マップは連想配列が欲しい場合に使う。
マップの値の取り出し方は以下のようにする。
iex> nums = %{'a' => 1, 'b' => 2, 'c' => 3}
=> %{'a' => 1, 'b' => 2, 'c' => 3}
iex> nums['a']
=> 1
キーがアトムの場合はドットで取得できる
iex> nums = %{a: 1, b: 2, c: 3}
=> %{a: 1, b: 2, c: 3}
iex> nums.a
=> 1
バイナリ
<< >>
で囲うとバイナリ型となる。
iex> bin = <<1, 2>>
=> <<1, 2>>
iex> byte_size bin
=> 2
名前
Elixir の識別子には、大文字・小文字の ASCII 文字、数字、アンダースコアで構成される。末尾には !
, ?
を使用できる。
モジュール、レコード、プロトコル、ビヘイビアは大文字始まりのキャメルケースで表される。その他の識別子は全て、小文字かアンダースコアで始まるスネークケースで表す。
アンダースコアで、その変数が使われないことを表明している。
その他、慣習などはスタイルガイドにまとまっている。
真偽値
Elixir にはブール演算のために true
, false
, nil
の特別な値を用意している。
nil
はブール演算において false
を表す。
変数スコープ
Elixir はレキシカルスコープになっており、スコープの基本単位は関数である。
関数内で定義された変数は関数内でしか参照できない。また、モジュール内に変数を定義した場合は、そのモジュールのトップレベルからアクセスできず、関数からアクセスすることはできない。
with
with を使えば、上記とは別に独自スコープを定義することができる。
iex> a = 'hoge'
=> 'hoge'
iex> b = with a = 'fuga', do: a
=> 'fuga'
iex> a
=> 'hoge'
with 式内で a
に 'fuga'
を束縛しているが、外側の a
には影響していない。
以上が Elixir の基本的な変数の型と扱いである。