Elixir 如何检查映射是否也是结构?

Elixir 如何检查映射是否也是结构?,elixir,Elixir,在Elixir中,我可以通过调用有意义的函数来检查变量是map还是struct,因为我想区分两者。我知道我可以在一个结构上调用\uuuuuuuuuuuuuuuuuuuuuu来获取它的模块名,但在普通映射上调用它会抛出: **(KeyError)键:%{ 所以我的问题是,如何检查变量是映射还是结构? 示例用例: #我希望在模块中以不同的方式处理结构和映射输入 定义模块的不同内容 def do_something(arg)何时是_map(arg)do #用地图做点什么 结束 def do_som

在Elixir中,我可以通过调用有意义的函数来检查变量是
map
还是
struct
,因为我想区分两者。我知道我可以在一个结构上调用
\uuuuuuuuuuuuuuuuuuuuuu
来获取它的模块名,但在普通映射上调用它会抛出:

**(KeyError)键:%{
所以我的问题是,如何检查变量是映射还是结构?


示例用例:

#我希望在模块中以不同的方式处理结构和映射输入
定义模块的不同内容
def do_something(arg)何时是_map(arg)do
#用地图做点什么
结束
def do_something(arg)何时是结构(arg)do
#但处理结构的方式不同
#问题是,`is_struct`不存在
结束
结束

您可以使用
map.keys/1
轻松检查当前地图的

对于map和struct
is_map/1
将返回true,但在您的示例中:

Map.keys(%{}) will return []

将返回密钥集合,例如
[:\uuuuu struct\uuuuu,:name,:age]

因此,您可以简单地使用:

:__struct__ in Map.keys(struct).

如果您想让此
为结构,请将其设置为宏。

通常要检查映射是否为结构:

Map.has_key?(struct, :__struct__)
对于不同的方法声明(第二个是更通用的方法):


对于带有保护的Map和Struct,不能有单独的函数头,但可以通过模式匹配来实现

defmodule Guard do

  def foo(%{:__struct__ => x })  do
    Struct
  end

  def foo(x) when is_map x do
    Map
  end

end

可以像下面这样在struct和map之间进行模式匹配

defmodule DifferentThings do
  def do_something(arg = %_x{}) do
    IO.puts "This is a struct"
  end

  def do_something(arg = %{}) do
    IO.puts "This is a map"
  end
end

检查术语是否为地图的最简单方法是使用:

Map.has_键?(Map,:_结构)
它在保护中不起作用,因此我们以前不得不求助于模式匹配function子句中的
:\uuuuu struct\uuuu
键:

def some_fun(%\uuuuu struct\uuuu:\u module}),do:。。。
但这件衣服看起来很脏


警卫:
是结构/1
从Erlang/OTP 21开始,我们引入了两个新的防护装置,可用于定义我们自己的防护装置:

defguard在is_map(term)和:erlang.is_map_键(:_struct_,term)时为_struct(term)
当defguard是_struct(term)时,它是_struct(term,module)并且:erlang.map_get(:uuuu struct_u,term)==module
现在,您可以将其用作功能保护:

def do_some(account)结构(account,User)什么时候做
#使用%User{}结构执行某些操作
结束
什么时候做什么
#用随机结构做一些事情
结束
什么时候做什么
#用地图做点什么
结束


注意:这些将很快添加到Elixir标准库中。按照本文中的讨论进行操作。

如前所述,介绍了防护装置。因此,您的原始代码将正常工作。

这太完美了!谢谢大家!<代码>地图。有_键?(struct,:_struct_uu)
@OleksandrAvoyants-那好多了。请将其作为答案发布。如果您需要模式匹配,可以使用
%{{code>arg=%{x}
非常喜欢
arg=%{code>,但您也可以使用
arg=%{}
defmodule Guard do

  def foo(%{:__struct__ => x })  do
    Struct
  end

  def foo(x) when is_map x do
    Map
  end

end
defmodule DifferentThings do
  def do_something(arg = %_x{}) do
    IO.puts "This is a struct"
  end

  def do_something(arg = %{}) do
    IO.puts "This is a map"
  end
end