【问题标题】:number_in_month exercise (smlnj how to iterate a value)number_in_month 练习(smlnj 如何迭代一个值)
【发布时间】:2022-03-07 06:47:56
【问题描述】:

我是函数式编程的新手,但我有专门的 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

【问题讨论】:

  • 你在思考可变值,这意味着你在思考命令式而不是函数式。你当然可以给一个值加 1,但你不能(通过使用 SML 的纯函数部分)使一个值发生变异,从而使其比其当前值多 1。
  • 对不起,我是函数式编程的新手,我应该如何处理这个问题?你能给我一个我能理解的例子或链接吗:D 谢谢:)

标签: sml smlnj


【解决方案1】:

通过迭代更新可变变量的等效方法是通过递归重新绑定不可变函数参数。因此,在伪代码中,不是“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)

【讨论】:

    【解决方案2】:

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

    回想一下这个问题,“它需要返回 1 以防匹配,否则返回 0”——这意味着在其内部调用函数可能会返回 1 两次,调用它 3 次将返回a 1 3 次等。现在,只需将递归函数调用实际返回 1 的所有成功次数相加即可。不要担心无限递归,否则它将返回 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-16
      相关资源
      最近更新 更多