你如何检查Elixir中的variablestypes

在Elixir中,你如何检查Python中的types:

>>> a = "test" >>> type(a) <type 'str'> >>> b =10 >>> type(b) <type 'int'> 

我在Elixir中读到了types检查器,比如'is_bitstring','is_float','is_list','is_map'等,但是如果你不知道types是什么?

没有直接的方法来获取Elixir / Erlang中的variablestypes。

你通常想知道一个variables的types,以便采取相应的行动; 您可以使用is_*函数来根据variables的types进行操作。

了解你一些Erlang在Erlang(Elixir)中input一个很好的章节 。

使用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 

从elixir 1.2开始,在iex中有一个i命令,它将列出任何Elixirvariables的types和更多。

 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中的任何数据types实现一个函数,那么这样做的方法就是定义一个协议和协议的实现,用于你希望函数处理的所有数据types。 不幸的是,你不能在守卫中使用协议function。 但是,一个简单的“types”协议将会非常直接的实现。

另一种方法是使用模式匹配。 假设你正在使用Timex,它使用%DateTime{}结构,并且你想看看一个元素是否是一个。 您可以在方法中使用模式匹配find匹配项。

 def is_a_datetime?(%DateTime{}) do true end def is_a_datetime?(_) do false end 

另外为了debugging的目的,如果你不在iex中,你可以直接调用它:

 IEx.Info.info(5) => ["Data type": "Integer", "Reference modules": "Integer"] 

为了有人希望搞清楚一个真正理智的版本,我会在这里留下。 目前没有好的答案,这在谷歌即将上演…

 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" _ -> "idunno" end end end 

为了完整起见,testing用例:

 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 

这是一个协议的解决scheme; 我不确定他们是否更快(我当然希望他们没有对所有types进行循环),但是它非常丑陋(而且很脆弱;如果他们添加或删除基本types或重命名,则会打破它)。

 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 

我碰到一个情况需要检查参数是否需要确定types。 也许可以主动更好的方法。

喜欢这个:

 @required [{"body", "binary"},{"fee", "integer"}, ...] defp match_desire?({value, type}) do apply(Kernel, :"is_#{type}", [value]) end 

用法:

 Enum.map(@required, &(match_desire?/1))