Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 616
John Ostin Avatar asked Jan 17 '13 07:01

John Ostin


Video Answer


2 Answers

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)
like image 75
pad Avatar answered Oct 08 '22 12:10

pad


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
like image 29
Jesper.Reenberg Avatar answered Oct 08 '22 12:10

Jesper.Reenberg