# [erlang-questions] Pattern Matching Question

Esbjörn Dominique <>
Fri Nov 23 21:47:00 CET 2007

```hi Justin,

My advice would be to turn your days_in to a helper function, e.g.
days_in1, something like:

days_in1(jan, _) -> 31;
days_in1(feb, common) -> 28;
days_in1(feb, leap) -> 29;
days_in1(mar, _) -> 31;
days_in1(apr, _) -> 30;
days_in1(may, _) -> 31;
days_in1(jun, _) -> 30;
days_in1(jul, _) -> 31;
days_in1(aug, _) -> 31;
days_in1(sep, _) -> 30;
days_in1(oct, _) -> 31;
days_in1(nov, _) -> 30;
days_in1(dec, _) -> 31.

days_in(Month, common) ->
days_in1(Month, common);
days_in(Month, leap) ->
days_in1(Month, leap);
days_in(Month, Year) when is_integer(Year) ->
days_in1(Month, leap(Year)).

leap(Year) when Year rem 400 == 0 -> leap   ;
leap(Year) when Year rem 100 == 0 -> common ;
leap(Year) when Year rem   4 == 0 -> leap   ;
leap(Year) when integer(Year)     -> common .

And only export days_in/2, ofcourse.

What do you think?
/esbjörn

On Nov 23, 2007 8:45 PM, Justin Piper <> wrote:
> I'm working through an introductory tutorial on Erlang, and one of the
> exercises asked for a function that returns the number of days in a
> given month, which I implemented this way:
>
>    days_in(jan, _     ) ->          31 ;
>    days_in(feb, common) -> 28          ;
>    days_in(feb, leap  ) ->    29       ;
>    days_in(mar, _     ) ->          31 ;
>    days_in(apr, _     ) ->       30    ;
>    days_in(may, _     ) ->          31 ;
>    days_in(jun, _     ) ->       30    ;
>    days_in(jul, _     ) ->          31 ;
>    days_in(aug, _     ) ->          31 ;
>    days_in(sep, _     ) ->       30    ;
>    days_in(oct, _     ) ->          31 ;
>    days_in(nov, _     ) ->       30    ;
>    days_in(dec, _     ) ->          31 ;
>
>    days_in(Month, Year)
>    -> days_in(Month, leap(Year)) .
>
>    leap(Year) when Year rem 400 == 0 -> leap   ;
>    leap(Year) when Year rem 100 == 0 -> common ;
>    leap(Year) when Year rem   4 == 0 -> leap   ;
>    leap(Year) when integer(Year)     -> common .
>
> You can either explicitly tell days_in/2 if it is a leap year using
> 'common' and 'leap', or you can give it an integer and it will
> determine whether it is a leap year.
>
> This works, but as you can see, since February is the only month that
> is actually different during a leap year, it's the only one that cares
> what you pass in the second argument. Since passing something other
> than 'leap', 'common' or an integer is surely an error, it'd be nice
> if this were indicated for all of the months. Does Erlang provide an
> elegant way to do this? I know I could just have two clauses for each
> month:
>
>    days_in(jan, common) -> 31 ;
>    days_in(jan, leap  ) -> 31 ;
>
> But that seems like needless duplication. I also know I could rewrite
> days_in/2 to have just one clause for all twelve months and just use
> case to select the correct number of days:
>
>    days_in(Month, Year)
>    when Year == common; Year == leap
>    -> case { Month, Year }
>       of { jan, _     } ->          31 ;
>          { feb, common} -> 28          ;
>          { feb, leap  } ->    29       ;
>          { mar, _     } ->          31 ;
>          { apr, _     } ->       30    ;
>          { may, _     } ->          31 ;
>          { jun, _     } ->       30    ;
>          { jul, _     } ->          31 ;
>          { aug, _     } ->          31 ;
>          { sep, _     } ->       30    ;
>          { oct, _     } ->          31 ;
>          { nov, _     } ->       30    ;
>          { dec, _     } ->          31
>       end;
>
> But I think that the version that uses a clause per month is a little
> easier to read, particularly if you're just scanning the code. I was
> hoping Erlang would have an easy way to say that the second argument
> has to be either 'leap', 'common' or an integer, and that anything
> else is an error.
> _______________________________________________
> erlang-questions mailing list
>
> http://www.erlang.org/mailman/listinfo/erlang-questions
>

--
Esbjörn Dominique
OptiMobile AB
+46(0)706 - 305 590
+46(0)8 - 750 61 90

```