Dans Elixir, comment vérifier le type tel qu'en Python:
>>> a = "test"
>>> type(a)
<type 'str'>
>>> b =10
>>> type(b)
<type 'int'>
J'ai lu dans Elixir qu'il y a des vérificateurs de type tels que 'is_bitstring', 'is_float', 'is_list', 'is_map', etc.
Il n'y a pas de moyen direct d'obtenir le type d'une variable dans Elixir/Erlang.
Vous voulez généralement connaître le type d'une variable afin d'agir en conséquence; vous pouvez utiliser les fonctions is_*
pour agir en fonction du type d'une variable.
Learn You Some Erlang a un beau chapitre à propos de la frappe à Erlang (et donc à Elixir).
La manière la plus idiomatique d’utiliser la famille de fonctions is_*
serait probablement de les utiliser dans des correspondances de modèle:
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
À partir de elixir 1.2, il existe une commande i
dans iex qui répertorie le type et plus d'une variable Elixir.
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
Si vous regardez dans le code de la commande i
, vous verrez que cela est implémenté via un protocole.
https://github.com/elixir-lang/elixir/blob/master/lib/iex/lib/iex/info.ex
Si vous souhaitez implémenter une fonction pour tout type de données dans Elixir, vous devez définir un protocole et l'implémenter du protocole pour tous les types de données sur lesquels vous souhaitez que la fonction fonctionne. Malheureusement, vous ne pouvez pas utiliser une fonction de protocole dans les gardes. Cependant, un protocole simple "type" serait très simple à mettre en œuvre.
Une autre approche consiste à utiliser une correspondance de modèle. Supposons que vous utilisez Timex, qui utilise une structure %DateTime{}
, et que vous voulez voir si un élément en est un. Vous pouvez trouver une correspondance à l'aide de la correspondance de modèle dans la méthode.
def is_a_datetime?(%DateTime{}) do
true
end
def is_a_datetime?(_) do
false
end
Également à des fins de débogage, si vous n'êtes pas dans iex, vous pouvez l'appeler directement:
IEx.Info.info(5)
=> ["Data type": "Integer", "Reference modules": "Integer"]
Je vais laisser cela ici pour que quelqu'un puisse espérer trouver une version réellement saine. Pour le moment, il n'y a pas de bonne réponse à cette question sur Google ...
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
Par souci d'exhaustivité, cas de test:
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
Voici une solution avec des protocoles; Je ne sais pas s'ils sont plus rapides (j'espère bien qu'ils ne font pas une boucle sur tous les types), mais c'est assez moche (et fragile; s'ils ajoutent ou suppriment un type de base ou le renomment, cela le cassera).
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
Je viens de coller le code de 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
Juste parce que personne n'en a parlé
IO.inspect/1
Sorties pour consolider l'objet ... c'est presque l'équivalent de JSON.stringify
Très utile lorsque vous ne pouvez pas comprendre la nature d'un objet dans un test.
Je suis tombé sur une situation nécessitant de vérifier le paramètre doit être certain type. Peut-être peut-être actif d'une meilleure façon.
Comme ça:
@required [{"body", "binary"},{"fee", "integer"}, ...]
defp match_desire?({value, type}) do
apply(Kernel, :"is_#{type}", [value])
end
Usage:
Enum.map(@required, &(match_desire?/1))