John Ostin
John Ostin

Reputation: 391

SML and functional coding style

I'm start to learn Standard ML with Programming languages course.

In the first homework, I try to write a function is_older that takes two dates and evaluates to true or false. It evaluates to true if the first argument is a date that comes before the second argument (If the two dates are the same, the result is false.).

So I write the following code:

fun is_older(first: int * int * int, second: int * int * int) =
  if(#1 first = #1 second andalso #2 first = #2 second andalso #3 first = #3 second) then false
  else if (#1 first < #1 second) then true
  else if (#1 first = #1 second andalso #2 first < #2 second) then true
  else if (#1 first = #1 second andalso #2 first = #2 second andalso #3 first < #3 second) then true
  else false

The code is works fine, but it looks ugly.

How can I rewrite this code in functional style?

Upvotes: 6

Views: 2449

Answers (3)

Rupam
Rupam

Reputation: 11

fun is_older((yr1 : int , mo1 : int , dt1 : int), (yr2 : int , mo2 : int , dt2 : int )) =
  yr1 < yr2 orelse (yr1 = yr2 andalso mo1 < mo2) 
  orelse (yr1 = yr2 andalso mo1 = mo2 andalso dt1 < dt2)

Upvotes: 1

Jesper.Reenberg
Jesper.Reenberg

Reputation: 5944

In general when you have something on the form

if b then
  true
else
  false

you should exchange it with just b, as it is seen trivially to be the same. The solution provided by pad would probably also have been my solution, as it is nice and short.

However when you end up having those nasty/nested if-then-else's, and you don't return something simple (e.g., true/false or a number), then you should consider using a case. Your function is not a prime candidate to use, however I hope the below still shows the idea (that you easily can make structure of those nested if's)

fun is_older((y1, m1, d1), (y2, m2, d2)) =
    case (Int.compare(y1,y2), Int.compare(m1,m2), Int.compare(d1, d2)) of
      (LESS , _    , _   ) => true
    | (EQUAL, LESS , _   ) => true
    | (EQUAL, EQUAL, LESS) => true
    | _ => false

Upvotes: 9

pad
pad

Reputation: 41290

Two suggestions:

  • Use pattern matching to decompose tuples.
  • Use boolean operators (andalso, orelse, etc.) when if/else constructs return boolean.

A more readable version:

(* Compare two dates in the form of (year, month, day) *)
fun is_older((y1, m1, d1), (y2, m2, d2)) =
  y1 < y2 orelse (y1 = y2 andalso m1 < m2) 
  orelse (y1 = y2 andalso m1 = m2 andalso d1 < d2)

Upvotes: 13

Related Questions