답변:
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
typeof(variable)
?
foo = [1, "hello", [1, 2, 3]]
코드를 사용하여 코드 위에 매핑 될 수 없으며 Enum.map(foo, fn(x) -> IO.puts x end)
, 당신에게 작은 얼굴들을 보여줄 것입니다 (시도하십시오!). 따라서 목록이 목록 인 경우에만 검사가 필요하지만 대부분의 경우 필요하지 않은 경우에도 검사를 사용해야합니다. typeof를 사용하면 if 문 (O (n))을 사전 조회 (O (1))로 바꿀 수 있습니다.
Printable
정수 목록과 같이 인쇄 동작을 래핑하고 변경하는 자체 프로토콜을 구현할 수 있습니다 . Erlang 코드와 함께 사용하지 마십시오. 메시지 대신 정수 목록이 표시되는 이유를 궁금해 할 것입니다.
elixir 1.2부터는 i
iex에 유형과 더 많은 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에서 모든 데이터 유형에 대한 함수를 구현하려는 경우 기능을 수행하려는 모든 데이터 유형에 대한 프로토콜 및 프로토콜 구현을 정의하는 방법입니다. 안타깝게도 경비원에서는 프로토콜 기능을 사용할 수 없습니다. 그러나 간단한 "유형"프로토콜은 구현하기가 매우 간단합니다.
undefined function i/1
&i/1
의 기능입니다 IEx.Helpers
. &IEx.Helpers.i/1
바닐라 엘릭서에 넣으면 에 응용 프로그램으로 CompileError
포함되지 않은 경우를 생성 :iex
합니다 mix.exs
.
또 다른 방법은 패턴 일치를 사용하는 것입니다. %DateTime{}
구조체 를 사용하는 Timex를 사용하고 있고 요소가 하나인지 알고 싶다고 가정 해보십시오 . 메소드에서 패턴 일치를 사용하여 일치를 찾을 수 있습니다.
def is_a_datetime?(%DateTime{}) do
true
end
def is_a_datetime?(_) do
false
end
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과 거의 같습니다.
당신의 인생을 테스트 할 때 물체가 어떻게 보이는지 알아낼 수 없을 때 매우 유용합니다.