回答:
Elixir / Erlangで変数の型を直接取得する方法はありません。
通常は、それに応じて動作するために変数のタイプを知りたいです。is_*
変数のタイプに基づいて機能するために関数を使用できます。
Learn You一部のErlangには、 Erlang(つまりElixir)での入力に関する素晴らしい章があります。
is_*
関数のファミリーを使用する最も慣用的な方法は、おそらくパターンマッチでそれらを使用することでしょう:
def my_fun(arg) when is_map(arg), do: ...
def my_fun(arg) when is_list(arg), do: ...
def my_fun(arg) when is_integer(arg), do: ...
# ...and so on
typeof(variable)
か?
foo = [1, "hello", [1, 2, 3]]
コードをEnum.map(foo, fn(x) -> IO.puts x end)
試してみてください)、コードを使用してマッピングできません。そのため、inspectはリストの場合にのみ必要ですが、それ以外の場合はほとんど必要ないのに、inspectを使用する必要があります。typeofを使用すると、ifステートメント(O(n))を辞書検索(O(1))に変換できます。
Printable
整数のリストなど、印刷の動作をラップして変更する独自のプロトコルを実装できます。Erlangコードでは使用しないでください。そうしないと、メッセージの代わりに整数のリストが表示されるのではないかと不思議に思います。
elixir 1.2以降、i
すべてのElixir変数のタイプなどをリストするコマンドがiexにあります。
iex> foo = "a string"
iex> i foo
Term
"a string"
Data type
BitString
Byte size
8
Description
This is a string: a UTF-8 encoded binary. It's printed surrounded by
"double quotes" because all UTF-8 encoded codepoints in it are printable.
Raw representation
<<97, 32, 115, 116, 114, 105, 110, 103>>
Reference modules
String, :binary
i
コマンドのコードを見ると、これがプロトコルを介して実装されていることがわかります。
https://github.com/elixir-lang/elixir/blob/master/lib/iex/lib/iex/info.ex
Elixirで任意のデータ型の関数を実装する場合、その方法は、関数を操作するすべてのデータ型のプロトコルとプロトコルの実装を定義することです。残念ながら、ガードではプロトコル関数を使用できません。ただし、単純な「タイプ」プロトコルの実装は非常に簡単です。
undefined function i/1
&i/1
はの関数IEx.Helpers
です。&IEx.Helpers.i/1
バニラエリクサーに入れると、アプリケーションにCompileError
を含めない限り、を生成:iex
しますmix.exs
。
別のアプローチは、パターンマッチングを使用することです。%DateTime{}
構造体を使用するTimexを使用していて、要素が1つであるかどうかを確認するとします。メソッドでパターンマッチングを使用して一致を見つけることができます。
def is_a_datetime?(%DateTime{}) do
true
end
def is_a_datetime?(_) do
false
end
switch
/ ではなくパターンマッチングによって適切に動作しますcase
。
誰かが実際に健全なバージョンを理解できるように、これをここに残しておきます。現時点では、これがグーグルで出てくるのに良い答えはありません...
defmodule Util do
def typeof(self) do
cond do
is_float(self) -> "float"
is_number(self) -> "number"
is_atom(self) -> "atom"
is_boolean(self) -> "boolean"
is_binary(self) -> "binary"
is_function(self) -> "function"
is_list(self) -> "list"
is_tuple(self) -> "tuple"
true -> "idunno"
end
end
end
完全を期すために、テストケース:
cases = [
1.337,
1337,
:'1337',
true,
<<1, 3, 3, 7>>,
(fn(x) -> x end),
{1, 3, 3, 7}
]
Enum.each cases, fn(case) ->
IO.puts (inspect case) <> " is a " <> (Util.typeof case)
end
これがプロトコルを使用したソリューションです。彼らがより速いかどうかはわかりませんが(すべてのタイプでループを実行していないことを願っています)、それはかなり醜いです(そして壊れやすいです。基本的なタイプを追加または削除したり、名前を変更すると、それが壊れます)。
defprotocol Typeable, do: def typeof(self)
defimpl Typeable, for: Atom, do: def typeof(_), do: "Atom"
defimpl Typeable, for: BitString, do: def typeof(_), do: "BitString"
defimpl Typeable, for: Float, do: def typeof(_), do: "Float"
defimpl Typeable, for: Function, do: def typeof(_), do: "Function"
defimpl Typeable, for: Integer, do: def typeof(_), do: "Integer"
defimpl Typeable, for: List, do: def typeof(_), do: "List"
defimpl Typeable, for: Map, do: def typeof(_), do: "Map"
defimpl Typeable, for: PID, do: def typeof(_), do: "PID"
defimpl Typeable, for: Port, do: def typeof(_), do: "Port"
defimpl Typeable, for: Reference, do: def typeof(_), do: "Reference"
defimpl Typeable, for: Tuple, do: def typeof(_), do: "Tuple"
IO.puts Typeable.typeof "Hi"
IO.puts Typeable.typeof :ok
https://elixirforum.com/t/just-created-a-typeof-module/2583/5からコードを貼り付けるだけです:)
defmodule Util do
types = ~w[function nil integer binary bitstring list map float atom tuple pid port reference]
for type <- types do
def typeof(x) when unquote(:"is_#{type}")(x), do: unquote(type)
end
end
誰も言っていないから
IO.inspect/1
オブジェクトをコンソールする出力... JSON.stringifyとほぼ同等
テストでオブジェクトがどのように見えるかを理解することができない場合に非常に役立ちます。