【问题标题】:Just Started Learning SML: How to take two ints and return the list of all ints between刚开始学习 SML:如何取两个整数并返回其间所有整数的列表
【发布时间】:2015-04-29 15:52:52
【问题描述】:

和标题说的差不多。我刚开始学习 SML,但我的第一个项目遇到了麻烦。我知道这是一个非常基本的问题,用 java 之类的东西做起来对我来说非常容易,但我很难理解 SML。我需要编写一个函数 intsFromTo。它应该接受一对整数,低和高,并返回一个按升序排列的连续整数列表,即所有大于或等于低且小于或等于高的整数。

这是我目前所拥有的

fun intsFromTo (low,high) = val intList = []
if low >= high then nill
else intList::low intsFromTo(low+1,high);

我遇到了以下我也难以理解的错误。

http://i.imgur.com/QZ0WT6j.png

我们将不胜感激。

【问题讨论】:

    标签: sml smlnj ml


    【解决方案1】:

    您的代码中有几个问题,只需揭示隐藏的部分以查看答案,但我只是先给出提示以帮助您自己解决。

    1. 函数体的语法是什么?

    回想一下,在定义局部值时,函数体需要 let ... in ... end,就像您使用 intList 所做的那样:

    1. nill 的值是多少?

    你的意思可能是nil[]

    1. 你想用intList::low intsFromTo(low+1,high)表达什么?

    你的那部分几乎是正确的:你的目标是返回由当前low 元素组成的列表,然后是从其后继元素到最高元素的列表。这是写的:low :: intsFromTo (low+1,high)。长解释:你实际上并排写了 2 个不同的表达式(intList::low 和对intsFromTo 的递归调用),第一个不是函数,所以它不能应用于第二个(记住这是与 lambda 演算中的原理相同)。

    1. 然后呢?

      在这些更改之后,生成的程序应该可以编译,但它的实现可以改进(提示:intList?)。这留给读者作为练习。

    【讨论】:

    • 当然,这可能是家庭作业。在我看来,从长远来看,混淆部分答案并不能真正让互联网变得更好。这并不意味着我不欣赏帖子背后的努力或情感,只是这种方法更适合讨论论坛,而不是努力在互联网上放置清晰简洁正确信息的问答网站。
    • 我并没有真正考虑过这个问题,我发现了这个功能(它是由stackoverflow markdown implementation btw支持的,所以如果它不使用它为什么要包含它?),并决定然后用它,这似乎是个好主意。
    【解决方案2】:

    注意:代码在样式上可能更紧凑,但可能无法清楚地说明基本概念。

    典型递归

    fun intsFromTo(low, high) =
      let
          val out = []
      in
          if 
              low <= high
          then
              low :: intsFromTo2(low + 1, high)
          else
              out
      end
    

    替代方法

    另一种生成列表的方法是在列表上使用map-reduce 样式语义。

    fun intsFromTo(low, high) =
      if high > low         
      then     (* the list will contain at least one value *)
         if
           high >= 0
         then
           List.tabulate((high + 1) - low,
                    fn k => k + low)
         else
           List.rev(
              List.tabulate((~low + 1) + high,
                    fn k => ~k + high))
      else
          []    (* list empty: low >= high *)
    

    为什么选择替代方案? 只是出于好奇。

    性能

    轶事时间表明,第一个版本的速度大约是第二个版本的两倍:

    fun time() =
      let 
          val t = Timer.startCPUTimer();
      in
          intsFromTo(~1000000,1000000);
          Time.toReal(#usr(Timer.checkCPUTimer(t)))
      end
    

    至少在我的电脑用于其他用途时。

    【讨论】:

      【解决方案3】:

      迟到的答案,但这是一个可爱的紧凑递归定义。

      fun intList a b = if (a = b) then [b]
                        else a::intList (a+1) b;
      

      【讨论】:

      • 如果a &gt; b 会起作用吗?如果您在问题中使用了lowhigh,您会发现吗?
      猜你喜欢
      • 2011-11-05
      • 2020-10-28
      • 2023-01-20
      • 1970-01-01
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      相关资源
      最近更新 更多