2

I am trying to paint a room with walls into a map of %{{x, y} => [items]} and I am using a case statement to figure out what type of wall I want to draw.

However it sems to try to do pattern matching and assign pos to the values on left. (throwing illegal pattern compilation error)

I know I can prevent assignment with ^, but what about the cases where I need to do (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

How would you write this?

hakunin
  • 4,041
  • 6
  • 40
  • 57

1 Answers1

5

You cannot insert arbitrary expressions inside patterns. You'll have to either move the calculation outside and use the pin operator, or if it's simple arithmetic you can also use guards with when.

Moving outside:

sum_x = from_x + size_x
sum_y = from_y + size_y

case pos do
  {^from_x, ^from_y} -> ...
  {^from_x, ^sum_y} -> ...
  ...
end

Using guards:

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

Since you're not actually using much of the pattern matching specific functionality, you might want to use cond instead and do an equality check there so you don't have to use the pin operator everywhere or declare local variables outside:

cond do
  pos == {from_x, from_y} -> ...
  pos == {from_x, from_x + size_x} -> ...
  ...
end
Dogbert
  • 212,659
  • 41
  • 396
  • 397