我正在尝试使用以下代码“模拟”传递值结果函数,但似乎存在语法错误。我一直在浏览sml教程,但我很难搞清楚为什么这不起作用
1 val x = ref 0;
2 fun p(y': int ref)=
3 let
4 val y = !y'
5 in
6 let
7 y = 1
8 in
9 let x := 0
10 in
11 y' := y
12 end
13 end
14 end
15 p(x)
答案 0 :(得分:3)
在let <decs> in <exp>
中,<decs>
需要是一个或多个声明。
在你的情况下,在第7行你做y = 1
- 注意,这不是一个分配,而是一个比较。也就是说,在C ++中,它等同于执行y == 1
。您不能分配给非ref变量。 (通常,您希望尽可能避免使用ref变量。)
您可以在其位置val y = 1
进行操作,在这种情况下,您可以使用y
的名称创建一个新值,该值隐藏旧的y
(但不会更改它;您创建的是新价值)。
同样,在第9行,你做x := 0
,它不是一个声明,而是一个表达式,它将值0
赋给参考值x
,然后返回单位
此外,您可以在let语句中执行多个声明,因此您不需要执行嵌套。
最后,你在顶层写p(x)
。如果前面的声明以分号结尾,则只能在顶层上编写表达式;否则它认为它是声明的一部分。那是
val a = 5
6
被解释为
val a = 5 6
简而言之,您可以将其重写为:
val x = ref 0;
fun p(y': int ref)=
let
val y = !y' (* this line might as well be deleted. *)
val y = 1
in
x := 0;
y' := y
end;
p(x)
或者,更短的版本,因为SML具有良好的类型推断:
val x = ref 0;
fun p y' = (x := 0; y' := 1);
p x
但是,我会这样说;如果你来自C ++或类似的语言,可能很容易使用'a ref
,但你经常会发现,最小化它们的使用往往会导致SML中的代码更清晰。 (和其他功能语言。)
答案 1 :(得分:2)
let y = 1 ...
错了。 let x := 0
也是如此。在let ... in
内,您需要val
或fun
声明。
您似乎对SML有一些误解。 let
用于在范围中声明新的局部变量。您尝试在内部作用域中声明一个名为y
的变量,这很奇怪,该变量会隐藏您在直接外部作用域中的y
中声明的let
。你要么意味着两件事之一:
let var y = 1 in ...
另外,你有let x := 0
这很奇怪。 x := 0
本身就是一个有效的表达式。它更改x
指向的引用中包含的值。您不需要let
。由于x := 0
仅针对副作用进行评估,并且返回类型unit
(即没有用),您可能会熟悉;
运算符,您可以使用该运算符将一串串联起来评价最后一个结果的副作用“陈述”:x := 0; y' := y