SML:List.nth()函数在Let..in..end中不起作用?

时间:2013-01-20 12:33:52

标签: sml smlnj

我又回来了一个基本问题。 ;)

我学到了一些List函数。 “List.nth”就是其中之一。当我在SML命令窗口中使用此功能时,它工作正常。但是当在Let..in..end中使用时;块,它无法正常工作。

我希望,有人可以提供帮助。

let
  val actualDays = 0;

in
  actualDays = List.nth([10,20,31,50,45], 2);
  actualDays
end;

预期产出:

 val it = 31 : int

实际输出:

 val it = 0 : int

提前致谢!

2 个答案:

答案 0 :(得分:2)

这不符合您的意图的原因与List.nth函数或您在let表达式中的事实无关。这不符合您的意图的原因是=是SML中的相等运算符,而不是赋值运算符。

SML中唯一的赋值运算符是:=运算符,其左操作数必须是ref,而不是普通整数。因此,修复代码的一种方法是将actualDays更改为int ref而不仅仅是int,并使用:=代替=。然而,变异变量在SML中并不是非常惯用的。一个更好的解决方案是调整你的逻辑,不需要任何变异 - 可能是通过使用递归函数,或者,取决于你正在尝试做什么,更高阶函数。

答案 1 :(得分:1)

你需要放弃你的命令性思维",并开始思考"功能性思维"代替。例如

如上所述,除非是参考,否则您无法重新分配变量。如果你需要使用引用,那么你可能正在做它"错误"无论如何。 在函数式编程中,您实际上正在执行name binding(有时也称为单一赋值),而不是变量赋值。将它们视为"不可变对象"。

让我们先看看你的代码

let
  val actualDays = 0;    
in
  actualDays = List.nth([10,20,31,50,45], 2);
  actualDays
end;

当你在in ... end部分内放置一系列表达式时,它实际上与in ( expr_1; ... ; expr_n) end相同,请注意表示表达式序列的括号。一系列表达式从左到右计算每个表达式,忽略除最后一个表达式结果之外的所有表达式。因此,它主要用于评估具有副作用的表达

- (print "foo\n"; print "bar\n"; 3);
foo
bar
val it = 3 : int

在您的情况下,由于等号不是赋值运算符,而是比较运算符,因此您的第一个表达式将计算为布尔表达式,其被忽略"因为它没有副作用,然后返回actualDays的值,因为它是最后一个表达式。

修复示例的一种方法是将actualDays声明为List.nth的结果。那么你的函数可以带两个参数,一个参数是你期望获得的元素,另一个参数可以是你想要查找它的索引。

fun foo x i =
    let
      val actualDays = List.nth([10,20,31,50,45], i)
    in
      x = actualDays
    end

- foo 20 1;
val it = true : bool
- foo 50 3;
val it = true : bool

但是在这个特定的函数中,不需要let-expression,你也可以像这样写它

fun foo x i = x = List.nth([10,20,31,50,45], i)