我又回来了一个基本问题。 ;)
我学到了一些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
提前致谢!
答案 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)