刚开始学习 SML:如何取两个整数和 return 之间所有整数的列表

Just Started Learning SML: How to take two ints and return the list of all ints between

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

这是我目前所拥有的

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

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

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

任何帮助我前进的人都将不胜感激。

你的代码有几个问题,只要把隐藏的部分揭开就能看到答案,不过我只是先提示一下,帮助你自己解决。

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

回想一下,函数体在定义局部值时需要 let ... in ... end,就像您在 intList:

中所做的那样
  1. 价值是多少nill

你的意思可能是 nil,或者 []

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

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

  1. 然后呢?

    经过这些更改后,生成的程序应该可以编译,但它的实现可以改进(提示:intList?)。这留作 reader.

    的练习

注意:代码的风格可能更紧凑,但可能无法清楚地说明基本概念。

典型递归

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

至少在我的电脑上,当它被用于其他事情时。

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

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