How do you check for the type of variable in Elixir

前端 未结 8 1273
走了就别回头了
走了就别回头了 2021-01-30 15:25

In Elixir how do you check for type such as in Python:

>>> a = \"test\"
>>> type(a)

>>> b =10
>>> type(b         


        
相关标签:
8条回答
  • 2021-01-30 15:48

    Just because nobody has mentioned it

    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.

    0 讨论(0)
  • 2021-01-30 15:50

    There's no direct way to get the type of a variable in Elixir/Erlang.

    You usually want to know the type of a variable in order to act accordingly; you can use the is_* functions in order to act based on the type of a variable.

    Learn You Some Erlang has a nice chapter about typing in Erlang (and thus in Elixir).

    The most idiomatic way to use the is_* family of functions would probably be to use them in pattern matches:

    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
    
    0 讨论(0)
  • 2021-01-30 15:54

    Also for debugging purposes, if you're not in iex, you can call it directly:

    IEx.Info.info(5)
    => ["Data type": "Integer", "Reference modules": "Integer"]
    
    0 讨论(0)
  • 2021-01-30 15:59

    Starting in elixir 1.2 there is an i command in iex that will list the type and more of any Elixir variable.

    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
    

    If you look in the code for the i command you'll see that this is implemented via a Protocol.

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

    If you want to implement a function for any Data type in Elixir, the way to do that is to define a Protocol and implementation of the Protocol for all the data types you want the function to work on. Unfortunately, you can't use a Protocol function in guards. However, a simple "type" protocol would be very straightforward to implement.

    0 讨论(0)
  • 2021-01-30 16:00

    I'll just leave this here for the sake of somebody hopefully figuring out an actually sane version. At the moment there are no good answers to this coming up on 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
    

    For the sake of completeness, test cases:

    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
    

    Here's a solution with protocols; I am not sure if they are faster(I sure hope they are not doing a loop over all types), but it is pretty ugly(and fragile; if they add or remove a basic type or rename, it will break it).

    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
    
    0 讨论(0)
  • 2021-01-30 16:01

    I just paste the code from 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
    
    0 讨论(0)
提交回复
热议问题