2017-04-23 51 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