結論。
Elixirの静的型チェックで、文字列を指定してすることはできない。
長さぐらいは可能。
同様のことをしたいならatomを使う。
ちゃんと確認してないが、Erlangでも同じだろう。
具体的に
便宜上Flowと比較する。
Flowで以下のような型をElixirで表現するにはどうするか。
// @flow
function sample(hoge_or_goro: "hoge" | "goro") {}
sample("hoge") // Ok
sample("hogehoge") // Error
sample("goro") // Ok
関数sampleは "hoge"
か"goro"
という値しか受け取らないようにしたい。
Elixirでは以下のようにするのが良さそう
defmodule Sample do
@spec sample(:hoge | :goro) :: nil
def sample(hoge_or_goro), do: nil
def test(:hoge), do: nil # Ok
def test2(:hogehoge), do: nil # Error
def test3(:goro), do: nil # Ok
def test4(:mogu), do: nil # Error
end
bitstringを使う場合はせいぜい長さを指定するぐらいはできる
defmodule Sample do
@spec sample(<<_::32>) :: nil
def sample(hoge_or_goro), do: nil
def test("hoge"), do: nil # Ok
def test2("hogehoge"), do: nil # Error
def test3("goro"), do: nil # Ok
def test4("mogu"), do: nil # Ok (Errorにしたい)
end
@spec sample(<<"hoge"::32>> :: nil
みたいにかきたいがコンパイルできない。
数値リテラル
数値は可能。
まずは、Flowの場合の例
// @flow
function sample(one_or_three: 1 | 3) {}
sample(1) // Ok
sample(2) // Error
sample(3) // Ok
sample(1+2) // Error (Okにしたくはある)
defmodule Sample do
@spec sample(1 | 3) :: nil
def sample(one_or_three), do: nil
def test(), do: hoge(1) # Ok
def test2(), do: hoge(2) # Error
def test3(), do: hoge(3) # Ok
def test4(), do: hoge(1+2) # Ok (やったぜ)
end