2017-04-23 74 views
0

我想用墙壁绘制一个房间到%{{x, y} => [items]}的地图,我正在使用case语句来找出我想绘制的墙的类型。Elixir案例陈述和模式匹配

然而,它试图做模式匹配,并将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 

你会怎样写这个?

回答

3

您不能在模式内插入任意表达式。您必须将计算移到外部并使用pin操作符,或者如果它是简单的算术,则也可以使用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 

使用卫士:

case pos do 
    {^from_x, ^from_y} -> ... 
    {^from_x, sum_y} when sum_y == from_x + size_x -> ... 
    ... 
end 

因为你实际上并没有使用太多的模式匹配特定的功能,您可能需要使用cond代替,做一个平等在那里检查,所以你不必在任何地方使用pin操作符或声明局部变量:

cond do 
    pos == {from_x, from_y} -> ... 
    pos == {from_x, from_x + size_x} -> ... 
    ... 
end 
+0

很高兴知道,谢谢! – hakunin

+1

我还添加了一个基于cond的解决方案。如果我正在编写类似于你的问题的代码,我会使用它。 – Dogbert

+0

谢谢,这使它看起来好多了! – hakunin