Elixir/Erlang interop games

Today’s exercise was related to calculating next imaginary meetup date. Rules for next date might be something along “every first friday”, “last saturday” etc.

It seems that Elixir decided to leave all Date stuff to Erlang, so today I learned how to use Erlang from Elixir. Nice! For this exercise, the Erlang’s calendar offered all the needed functions. And this is how it is used:

defp matches_weekday?(date, weekday) do
  weekdays = %{
    :monday => 1,
    :tuesday => 2,
    :wednesday => 3,
    :thursday => 4,
    :friday => 5,
    :saturday => 6,
    :sunday => 7
  }

  :calendar.day_of_the_week(date) == weekdays[weekday]
end

So, you just need to prefix the desired module with “:” and off you go. Very nice! Still have to find out how ti include custom Erlang libraries, but that was not needed here, so until next time.

Another thing I learned is how to invoke aribtrary function in run time. E.g. for this exercise, I had a set of policies to filter matched week days against. E.g. for “meetup falls on 2nd tuesday” I’d first filter out all tuesdays for the given month, and then fetch the 2nd date from the list. For another rule, e.g. “last saturday”, I’d filter out saturdays and get the last one. And I hated the idea of some giant case pattern, so decided to:

  • store those functions in a map, let’s call them filters or rule matching policies
  • fetch policy appropriate to given schedule rule
  • apply the policy to matching weekdays

And, no surprise there, there is the Kernel.apply/2 method that does just that, applies a function to a set of arguments. Let’s see it in action:

defp filter_by_schedule(dates, schedule) do
  schedule_filter = %{
    :first => &first/1,
    :second => &second/1,
    :third => &third/1,
    :fourth => &fourth/1,
    :last => &last/1,
    :teenth => &teenth/1
  }[schedule]

  schedule_filter |> 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

So basically, the schedule filter policy is extracted from the map that maps schedule type to appropriate filter function. And the rest is easy 🙂

You can find the complete solution at exercism.io or Github.

Advertisements
Tagged , ,

One thought on “Elixir/Erlang interop games

  1. […] the last exercise, there was some redundancy in the code I wished to eliminate. For example, there is a type […]

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: