Wishful types

In the last exercise, there was some redundancy in the code I wished to eliminate.
For example, there is a type definition that defines possible week days:

@type weekday ::
  :monday |
  :tuesday |
  :wednesday |
  :thursday |
  :friday |
  :saturday |
  :sunday

So, someone invoking the meetup date calculation, would have to use one of the valid atoms for the desired day in the week.

Now, to match those agains Erlang’s calendar.day_of_the_week/1, I needed a way to match say :wednesday to 3, since day_of_the_week returns day number, not the atom fom above type.

An easy solution:

@weekdays %{
  :monday => 1,
  :tuesday => 2,
  :wednesday => 3,
  :thursday => 4,
  :friday => 5,
  :saturday => 6,
  :sunday => 7
}

No magic there, just repeat the atoms, map values from day_of_the_week on them, and off we go.

But, it would be much nicer if I could just do:

@weekdays weekday |> Enum.with_index(1) |> Enum.into(%{})

That would produce the exact same map, just in a dry way.

Another thing that could benefit from the same pattern was the schedule policy filtering.
So, say that we have a few functions we would like to map to a constant in the module and use like this:

@type schedule ::
  :first |
  :second |
  :third |
  :fourth |
  :last |
  :teenth

@schedules %{
  :first => &first/1,
  :second => &second/1,
  :third => &third/1,
  :fourth => &fourth/1,
  :last => &last/1,
  :teenth => &teenth/1
}

defp filter_by_schedule(dates, schedule) do
  @schedules[schedule] |> apply([dates])
end

defp first(dates) do
  dates |> hd
end

defp second(dates) do
  dates |> Enum.at(1)
end

defp third(dates) do
  dates |> Enum.at(2)
end

defp fourth(dates) do
  dates |> Enum.at(3)
end

defp last(dates) do
  dates |> Enum.reverse |> hd
end

defp teenth(dates) do
  dates |> Enum.find(fn({_, _, day}) ->
    day >= 13 && day <= 19
end)
end

That way, the @schedules map would be a constant, and the code would be much cleaner. Also, it would be nice if I could also:

 @schedules schedule |> Enum.map(fn(sch) -> %{sch => __info__(:functions)[sch]} end) |> Enum.into(%{})

Unfortunately, couldn’t find a way to acomplish this. So, if you have any suggestions, I’m all ears!

Advertisements
Tagged , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: