number_in_month练习(smlnj如何迭代一个值)

number_in_month exercise (smlnj how to iterate a value)

我是函数式编程的新手,但我在命令式编程方面有经验,特别是在 java 上。我想问一下 smlnj 中的值如何迭代 我知道在 java 上你可以使用 varName += anyNumber 或 varName = varName + 1。在 smlnj 上我不知道如何做到这一点,我的 var 值不是此处迭代是我的代码示例。提前致谢。

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

此程序将检查输入的日期(在列表中)是否在输入的月份存在,并将输出该月存在多少个日期。

例如:number_in_month ([(year,month,day)],monthEntered) number_in_month([(2017,2,1),(2015,2,3),(2012,1,2)],2) 输出必须是 2 因为列表中的第一项和第二项等于输入的月份。

我的代码中的问题是它只输出 1,即使我输入的所有日期都等于我输入的月份。我只想知道为什么它只输出 1 以及我应该如何修复它。提前致谢 :D

通过迭代更新可变变量的等效方法是通过递归重新绑定不可变函数参数。因此,在伪代码中,您不使用 "foo() { while (p) { x++; }}",而是使用 "foo(p,x) { if (p) { foo(p,x+1); } }"。或者在 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

但这是我如何编写一个函数,使用高阶函数过滤列表中属于给定月份的日期数:

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)

通常在不提供循环(for 或 while)的语言中,您的下一个选择应该始终是递归。在这种特殊情况下,递归调用此函数应该是您“增加”结果的方式。

倒过来想一下这个问题,“它需要 return 1 以防匹配,否则 0”——这意味着在其自身内部调用函数可能会 return a 1 两次,调用它 3 次将 return a 1 三次等。现在,这只是将递归函数调用的所有成功次数加起来实际上 returns 1 的问题。并且不要担心无限递归,因为它会 return 0 否则会使递归树崩溃。

fun number_in_month(dates: (int * int * int) list, month: int) =
    if null dates
    then 0
    else
        if #2 (hd dates) = month
        then 1 + number_in_month(tl dates, month) (* <--this is where the magic happens *)
        else number_in_month(tl dates, month)