smlsmlnj

number_in_month exercise (smlnj how to iterate a value)


im new in functional programming but i have experience in imperative programming specially on java. i would like to ask how does a value iterate in smlnj i know that on java you can use varName += anyNumber or varName = varName + 1. on smlnj i dont know how to do this and my var value is not iterating here is a sample of my code. thanks in advance.

fun number_in_month (dates : (int*int*int) list , month : int) =
    let
      val total = 0;
    in
      let
        fun check(date : (int*int*int) list , m : int) =
            if #2(hd(date)) = m
            then total + 1  (* this is the problem in the code i don't know
                               how to iterate this like "varName += 1" in java *) 
            else check(tl(date),m)     
      in
        check(dates,month)
      end
    end

this program will check if the dates (on a list) entered exist on the month entered and will output how many dates exist on the month.

for example : number_in_month ([(year,month,day)],monthEntered) number_in_month([(2017,2,1),(2015,2,3),(2012,1,2)],2) output must be 2 because the first and second item in the list is equal to the monthEntered.

the problem in my code is it just output 1 even if the all of the dates i input is equal to the month i enter. i just want to know why it just output 1 and how should i fix it. Thanks in advance :D


Solution

  • An equivalent of updating a mutable variable through iteration is re-binding an immutable function parameter through recursion. So instead of "foo() { while (p) { x++; }}", in pseudo-code, you do "foo(p,x) { if (p) { foo(p,x+1); } }". Or in SML,

    type date = {year : int, month : int, day : int}
    fun countMonth month (dates : date list) =
        let fun countMonth' [] count = count
              | countMonth' (d::ds) count =
                if #month d = month
                then countMonth' ds (count+1)
                else countMonth' ds count
        in countMonth' dates 0 end
    

    But here is how I'd write a function that filters the number of dates in a list that belong to a given month using a higher-order function:

    type date = {year : int, month : int, day : int}
    fun filterMonth month (dates : date list) =
        List.filter (fn d => #month d = month) dates
    fun countMonth month dates =
        List.length (filterMonth month dates)