[erlang-questions] Pattern Matching Question
Esbjörn Dominique
esbjorn.dominique@REDACTED
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 <justin.piper@REDACTED> 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
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions
>
--
Esbjörn Dominique
OptiMobile AB
+46(0)706 - 305 590
+46(0)8 - 750 61 90
esbjorn@REDACTED
More information about the erlang-questions
mailing list