Как вы проверяете тип переменной в Elixir
в Elixir как вы проверяете тип, например, в Python:
>>> a = "test"
>>> type(a)
<type 'str'>
>>> b =10
>>> type(b)
<type 'int'>
Я читал в эликсир есть тип шашки, такие как 'is_bitstring', 'is_float', 'is_list', 'is_map' и т. д., Но что делать, если вы понятия не имеете, что это может быть ?
8 ответов:
нет прямого способа получить тип переменной в Elixir / Erlang.
вы обычно хотите знать тип переменной, чтобы действовать соответственно; вы можете использовать
is_*функции для того, чтобы действовать на основе типа переменной.узнай, что у Эрланга есть хорошая глава о наборе текста в 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
начиная с elixir 1.2 есть
iкоманда в 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, способ сделать это-определить протокол и реализация протокола для всех типов данных, над которыми должна работать функция. К сожалению, вы не можете использовать функцию протокола в охранники. Однако простой протокол "типа" было бы очень просто реализовать.
другой подход заключается в использовании сопоставления шаблонов. Скажем, вы используете Timex, который использует
%DateTime{}struct, и вы хотите увидеть, является ли элемент одним. Вы можете найти совпадение, используя сопоставление шаблонов в методе.def is_a_datetime?(%DateTime{}) do true end def is_a_datetime?(_) do false end
также для целей отладки, если вы не находитесь в iex, вы можете вызвать его напрямую:
IEx.Info.info(5) => ["Data type": "Integer", "Reference modules": "Integer"]
Я просто оставлю это здесь ради того, чтобы кто-то, надеюсь, выяснил действительно здравую версию. На данный момент в 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для полноты картины, тестов:
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.преобразовать в строки
очень полезно, когда вы просто не можете за всю свою жизнь выяснить, как выглядит объект в тесте.
я наткнулся на ситуацию нужно проверить параметр должен быть определенного типа. Может быть, можно активнее лучший способ.
такой:
@required [{"body", "binary"},{"fee", "integer"}, ...] defp match_desire?({value, type}) do apply(Kernel, :"is_#{type}", [value]) endиспользование:
Enum.map(@required, &(match_desire?/1))
Comments