Нет прямого способа получить тип переменной в Elixir / Erlang.
Обычно вы хотите знать тип переменной, чтобы действовать соответствующим образом; вы можете использовать is_*
функции, чтобы действовать в зависимости от типа переменной.
В «Learn You Some 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)
потому что [1,2, 3] будут читаться как символы (почему erlang !!?), И покажет вам кучу улыбающихся лиц (попробуйте!). поэтому мы вынуждены использовать inspect, хотя inspect нужен только в том случае, если это список, в противном случае в большинстве случаев он нам не нужен. typeof позволяет нам превратить операторы if (O (n)) в поиск по словарю (O (1)).Printable
протокол, который обертывает и изменяет поведение печати, например списки целых чисел. Просто убедитесь, что вы не используете его с кодом Erlang, иначе вы будете ломать голову, задаваясь вопросом, почему вместо сообщений вы видите списки целых чисел.Начиная с elixir 1.2,
i
в iex есть команда, которая перечисляет тип и другие параметры любой переменной Elixir.Если вы посмотрите код
i
команды, вы увидите, что это реализовано через протокол.https://github.com/elixir-lang/elixir/blob/master/lib/iex/lib/iex/info.ex
Если вы хотите реализовать функцию для любого типа данных в Elixir, способ сделать это - определить протокол и реализацию протокола для всех типов данных, с которыми должна работать функция. К сожалению, вы не можете использовать функцию протокола в охранниках. Однако простой «типовой» протокол было бы очень просто реализовать.
источник
undefined function i/1
- то же самое для info / 1&i/1
это функция наIEx.Helpers
. Если вы добавите его&IEx.Helpers.i/1
в свой ванильный эликсир, вы создадите файл,CompileError
если только вы не включили его в:iex
качестве приложения в свойmix.exs
.Также для целей отладки, если вы не в iex, вы можете вызвать его напрямую:
источник
Другой подход - использовать сопоставление с образцом. Допустим, вы используете Timex, который использует
%DateTime{}
структуру, и хотите проверить, является ли элемент одним из них. Вы можете найти совпадение, используя сопоставление с образцом в методе.источник
switch
/case
.Я просто оставлю это здесь, чтобы кто-нибудь, надеюсь, придумал действительно разумную версию. На данный момент в 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
Для полноты картины тестовые примеры:
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
Очень полезно, когда вы всю жизнь не можете понять, как выглядит объект в тесте.
источник