IT story

Elixir에서 변수 유형을 확인하는 방법

hot-time 2020. 7. 2. 07:34
반응형

Elixir에서 변수 유형을 확인하는 방법


Elixir에서는 파이썬과 같은 유형을 어떻게 확인합니까?

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

Elixir에는 'is_bitstring', 'is_float', 'is_list', 'is_map'등과 같은 유형 검사기가 있지만 유형이 무엇인지 모를 경우 어떻게해야합니까?


Elixir / Erlang에서 변수 유형을 얻는 직접적인 방법은 없습니다.

일반적으로 그에 따라 행동하기 위해 변수의 유형을 알고 싶습니다. is_*변수 유형에 따라 작동하기 위해 함수를 사용할 수 있습니다 .

일부 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

elixir 1.2부터는 iiex에 유형과 더 많은 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

i명령 의 코드를 보면 이것이 프로토콜을 통해 구현되었음을 알 수 있습니다.

https://github.com/elixir-lang/elixir/blob/master/lib/iex/lib/iex/info.ex

Elixir에서 모든 데이터 유형에 대한 함수를 구현하려는 경우 기능을 수행하려는 모든 데이터 유형에 대한 프로토콜 및 프로토콜 구현을 정의하는 방법입니다. 안타깝게도 경비원에서는 프로토콜 기능을 사용할 수 없습니다. 그러나 간단한 "유형"프로토콜은 구현하기가 매우 간단합니다.


또한 디버깅 목적으로 iex가 아닌 경우 직접 호출 할 수 있습니다.

IEx.Info.info(5)
=> ["Data type": "Integer", "Reference modules": "Integer"]

또 다른 방법은 패턴 일치를 사용하는 것입니다. %DateTime{}구조체 를 사용하는 Timex를 사용하고 있고 요소가 하나인지 알고 싶다고 가정 해보십시오 . 메소드에서 패턴 일치를 사용하여 일치를 찾을 수 있습니다.

def is_a_datetime?(%DateTime{}) do
  true
end

def is_a_datetime?(_) do
  false
end

누군가가 실제로 제정신 버전을 알아 내기 위해 여기에 남겨 두겠습니다. 현재 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

Outputs to console the object ... its almost equiv to JSON.stringify

Very helpful when you just cannot for the life of you figure out what an object looks like in a test.


I came across a situation need to check the parameter need to be certain type. Maybe can active a better way.

Like this:

@required [{"body", "binary"},{"fee", "integer"}, ...]
defp match_desire?({value, type}) do
  apply(Kernel, :"is_#{type}", [value])
end

Usage:

Enum.map(@required, &(match_desire?/1))

참고URL : https://stackoverflow.com/questions/28377135/how-do-you-check-for-the-type-of-variable-in-elixir

반응형