No Elixir, como você verifica tipos, como em Python:
>>> a = "test"
>>> type(a)
<type 'str'>
>>> b =10
>>> type(b)
<type 'int'>
Li no Elixir que existem verificadores de tipos como 'is_bitstring', 'is_float', 'is_list', 'is_map' etc.
No Elixir, como você verifica tipos, como em Python:
>>> a = "test"
>>> type(a)
<type 'str'>
>>> b =10
>>> type(b)
<type 'int'>
Li no Elixir que existem verificadores de tipos como 'is_bitstring', 'is_float', 'is_list', 'is_map' etc.
Respostas:
Não existe uma maneira direta de obter o tipo de uma variável no Elixir / Erlang.
Você geralmente deseja saber o tipo de uma variável para agir em conformidade; você pode usar as is_*
funções para agir com base no tipo de uma variável.
Aprenda você Alguns Erlang tem um bom capítulo sobre como digitar Erlang (e, portanto, Elixir).
A maneira mais idiomática de usar a is_*
família de funções provavelmente seria usá-las em correspondências de padrões:
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]]
, com código Enum.map(foo, fn(x) -> IO.puts x end)
porque [1,2, 3] será lido como caracteres (por que erlang !!?) E mostrará um monte de rostos sorridentes (tente!). então somos forçados a usar a inspeção, mesmo que a inspeção seja necessária apenas se for uma lista; caso contrário, na maioria das vezes, não precisamos dela. typeof permite transformar as declarações if (O (n)) em pesquisas de dicionário (O (1)).
Printable
protocolo que envolve e altera o comportamento da impressão, por exemplo, listas de números inteiros. Apenas certifique-se de não usá-lo com o código Erlang - ou você estará coçando a cabeça se perguntando por que, em vez de mensagens, está vendo listas de números inteiros.
A partir do elixir 1.2, existe um i
comando no iex que lista o tipo e mais de qualquer variável do 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
Se você procurar no código o i
comando, verá que isso é implementado por meio de um protocolo.
https://github.com/elixir-lang/elixir/blob/master/lib/iex/lib/iex/info.ex
Se você deseja implementar uma função para qualquer tipo de dados no Elixir, a maneira de fazer isso é definir um protocolo e a implementação do protocolo para todos os tipos de dados nos quais você deseja que a função trabalhe. Infelizmente, você não pode usar uma função de protocolo nos guardas. No entanto, um protocolo "tipo" simples seria muito simples de implementar.
undefined function i/1
- mesmo para info / 1
&i/1
é uma função ativada IEx.Helpers
. Se você colocar &IEx.Helpers.i/1
no seu Elixir de baunilha, você gerará um, a CompileError
menos que tenha incluído :iex
como aplicativo no seu mix.exs
.
Outra abordagem é usar a correspondência de padrões. Digamos que você esteja usando o Timex, que usa uma %DateTime{}
estrutura, e deseja ver se um elemento é um. Você pode encontrar uma correspondência usando a correspondência de padrões no método
def is_a_datetime?(%DateTime{}) do
true
end
def is_a_datetime?(_) do
false
end
switch
/ case
.
Vou deixar isso aqui por causa de alguém, com sorte, descobrir uma versão realmente sã. No momento, não há boas respostas para isso chegando no 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"
true -> "idunno"
end
end
end
Por uma questão de integridade, casos de teste:
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
Aqui está uma solução com protocolos; Não tenho certeza se eles são mais rápidos (espero que eles não estejam fazendo um loop em todos os tipos), mas é muito feio (e frágil; se eles adicionarem ou removerem um tipo básico ou renomearem, isso será interrompido).
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
Acabei de colar o código em 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
Me deparei com uma situação precisa verificar o parâmetro precisa ser de determinado tipo. Talvez possa ativar uma maneira melhor.
Como isso:
@required [{"body", "binary"},{"fee", "integer"}, ...]
defp match_desire?({value, type}) do
apply(Kernel, :"is_#{type}", [value])
end
Uso:
Enum.map(@required, &(match_desire?/1))
Só porque ninguém mencionou
IO.inspect/1
Saídas para consolar o objeto ... é quase equivalente ao JSON.stringify
Muito útil quando você simplesmente não consegue descobrir como é um objeto em um teste.