Как вы проверяете тип переменной в Elixir



в Elixir как вы проверяете тип, например, в Python:



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


Я читал в эликсир есть тип шашки, такие как 'is_bitstring', 'is_float', 'is_list', 'is_map' и т. д., Но что делать, если вы понятия не имеете, что это может быть ?

435   8  

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

    Ничего не найдено.