2

I am implementing a function that takes two dates that are of type (int * int * int): the first part is the year, the second part is the month and the third part is the day. It should return true if the first date is older than the second.

I want to test the function and I'm having problems with that. This is the file ex1.sml

fun is_older(d1 : (int * int * int), d2 : (int * int * int)) =
    if #1 d1 < #2 d2 then
        true
    else if #2 d1 < #2 d2 then
        true
    else
        #3 d1 < #3 d2

And this is the file ex1-test.sml that should test the function:

use "ex1.sml"

val test1 = is_older ((1,2,3),(2,3,4)) = true

Whenever I try to run this last file, by loading in the REPL, I always end up with the error: Error: syntax error: replacing VAL with EQUALOP

However if I put the test in ex1.ml and load it in the REPL it doesn't give any error.

fun is_older(d1 : (int * int * int), d2 : (int * int * int)) =
    if #1 d1 < #2 d2 then
        true
    else if #2 d1 < #2 d2 then
        true
    else
        #3 d1 < #3 d2

val test1 = is_older ((1,2,3),(2,3,4)) = true

I would like to have the tests in a separate file which then includes the definitions and runs the tests, as I was trying to do above. Why doesn't it work?

John Coleman
  • 51,337
  • 7
  • 54
  • 119
plx
  • 397
  • 3
  • 15

2 Answers2

3

Somewhat oddly, this is one of the rare cases where semicolons are required in SML even outside the REPL. If you change your test file to:

use "ex1.sml";

val test1 = is_older ((1,2,3),(2,3,4)) = true

then it will work as expected. See this for more about semicolons in SML.

John Coleman
  • 51,337
  • 7
  • 54
  • 119
1

Since John found the bug, here is some code feedback:

  1. This is probably a case where records with named fields are better suited:

    type date = {year : int, month : int, day : int}
    

    This way you don't mix up the order of the otherwise interchangeable ints.

    Date formats are notoriously diverse. People might think it's y-m-d, m-d-y or d-m-y.

  2. Your function seems to have another bug:

    val test_this = is_older ((2000, 1, 1), (1999, 2, 2))
    

    But 2000 isn't older than 1999.

  3. Using if-then-else when the result is a boolean is slightly redundant:

    fun is_older (date1 : date, date2 : date) =
        #year date1  < #year date2 orelse
        #month date1 < #month date2 orelse
        #day date1   < #day date2
    

    (preserving the bug from 2.)

sshine
  • 15,635
  • 1
  • 41
  • 66
  • Yes there was a bug with the code and you're right that the code is redundant as it is. Thanks for the heads up. – plx Mar 07 '18 at 11:19