Elixir案例陈述和模式匹配

hak*_*nin 2 elixir pattern-matching case-statement

我正在尝试将%{{x, y} => [items]}一堵带有墙壁的房间涂成地图,并且正在使用一个案例声明来确定要绘制哪种类型的墙壁。

但是,尝试进行模式匹配并将其分配pos给左侧的值很困难。(引发illegal pattern编译错误)

我知道我可以阻止分配^,但是我该怎么办(from_y+sizey)呢?

def place_room({from_x, from_y}, {size_x, size_y}, original_map) do
  Enum.reduce from_x..(from_x + size_x-1), original_map, fn x, map ->
    Enum.reduce from_y..(from_y + size_y-1), map, fn y, map ->
      pos = {x, y}
      case pos do
        {from_x, from_y} ->
          place(map, pos, :wall, %{type: :room_wall_tl})
        {from_x, (from_y+size_y)} ->
          place(map, pos, :wall, %{type: :room_wall_tr})
        {from_x, (from_y+size_y)} ->
          place(map, pos, :wall, %{type: :room_wall_bl})
        {(from_x+size_x), (from_y+size_y)} ->
          place(map, pos, :wall, %{type: :room_wall_br})
        {_, _} ->
          place(map, pos, :floor, %{type: :room_floor})
        weird ->
            IO.inspect weird
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

你会怎么写呢?

Dog*_*ert 5

您不能在模式内插入任意表达式。您必须将计算移到外面并使用pin运算符,或者,如果它是简单的算术运算,则还可以将Guard与一起使用when

搬出:

sum_x = from_x + size_x
sum_y = from_y + size_y

case pos do
  {^from_x, ^from_y} -> ...
  {^from_x, ^sum_y} -> ...
  ...
end
Run Code Online (Sandbox Code Playgroud)

使用警卫:

case pos do
  {^from_x, ^from_y} -> ...
  {^from_x, sum_y} when sum_y == from_x + size_x -> ...
  ...
end
Run Code Online (Sandbox Code Playgroud)

由于实际上并没有使用很多与模式匹配的特定功能,因此您可能想cond改用它并在那里进行相等性检查,因此您不必在各处使用pin运算符或在外部声明局部变量:

cond do
  pos == {from_x, from_y} -> ...
  pos == {from_x, from_x + size_x} -> ...
  ...
end
Run Code Online (Sandbox Code Playgroud)