模式匹配一​​个空的MapSet

时间:2018-03-14 17:51:23

标签: elixir

给定一个MapSet,如何使用模式匹配检测它是否为空?

# What goes in the question marks?
def my_func(????), do: IO.puts("This mapset is empty")
def my_func(%MapSet{}), do: IO.puts("This mapset is not empty")

my_func(MapSet.new())

如果这是一个列表,我会在([])上匹配它,但这对MapSets不起作用(因为类型不同)

以下是我尝试过的其他一些事情,但未成功。

def myfunc([]), do: IO.puts("This only works for lists")
# This is a syntax error
# def myfunc(MapSize.new())

def myfunc(%MapSet{}), do: IO.puts("This matches every mapset")
def myfunc(a) when map_size(a), do: IO.puts("the map size is always 3")

3 个答案:

答案 0 :(得分:5)

MapSet将其条目存储在名为map的字段中。我不能100%确定这是实施细节还是保证保持不变,但现在您可以使用map检查map_size/1字段是否为空:

defmodule A do
  def empty?(%MapSet{map: map}) when map_size(map) == 0, do: true
  def empty?(%MapSet{}), do: false
end

IO.inspect A.empty?(MapSet.new)
IO.inspect A.empty?(MapSet.new([1, 2]))

输出:

true
false

答案 1 :(得分:3)

您也可以考虑the solution I provided for matching against an empty map如下:

defmodule A do
  def empty?(some_map_set = %MapSet{}) do
    an_empty_map_set = MapSet.new

    some_map_set
    |> case do
    ^an_empty_map_set ->true  # Application of pin operator
    _ -> false
    end
  end
end

您可以按如下方式进行测试:

A.empty?(MapSet.new)

A.empty?(MapSet.new([1]))

在该链接中,您可以看到可以相应利用的其他解决方案。 一个已经由@dogbert提供。 另一种解决方案可以如下工作:

defmodule A do
  @empty MapSet.new
  def empty?(some_map_set) when some_map_set == @empty, do: true
  def empty?(%MapSet{}), do: false
end

答案 2 :(得分:3)

实现目标有一种愚蠢但仍然合法的方式:

defmodule MapSetTest do
  def my_func(map_set, empty_map_set \\ MapSet.new)
  def my_func(empty_map_set, empty_map_set),
    do: IO.puts("This mapset is empty")
  def my_func(%MapSet{}, _),
    do: IO.puts("This mapset is not empty")
end

MapSetTest.my_func(MapSet.new)      #⇒ This mapset is empty
MapSetTest.my_func(MapSet.new([]))  #⇒ This mapset is empty
MapSetTest.my_func(MapSet.new([1])) #⇒ This mapset is not empty

这里的诀窍是,虽然我们不能直接在匹配中调用MapSet.new,但我们可以将其值指定为隐藏的第二个参数的默认值。