1

我正在尝试使用以下代码“模拟”按值传递结果函数,但似乎存在语法错误。我一直在浏览 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)
4

2 回答 2

3

let <decs> in <exp>, 中<decs>需要一个或多个声明。

在你的情况下,你在第 7 行y = 1- 注意,这不是一个分配,而是一个比较。也就是说,在 C++ 中它相当于做y == 1. 您不能分配给非参考变量。(通常,您希望尽可能避免使用 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 refsa 很多,但你会经常发现,最小化它们的使用通常会导致 SML 中的代码更清晰。(和其他函数式语言。)

于 2011-10-25T07:12:07.263 回答
2

let y = 1 ...是错的。也是如此let x := 0。在里面let ... in,你需要valorfun声明。

看来你对 SML 有一些误解。let用于在范围内声明新的局部变量。尝试声明一个y在内部范围中命名的变量会影响y您在let直接外部范围中声明的变量,这对您来说很奇怪。你要么意味着两件事之一:

  1. 更改在外部范围中定义的“y”变量的值。这是不可能的。您不能在 ML 中更改变量的值
  2. 您想声明一个新的、不相关的变量,也称为“y”,并在此范围内隐藏以前的“y”;在这种情况下,您将使用let var y = 1 in ...

另外,你有let x := 0. x := 0本身就是一个有效的表达式。它更改 指向的引用中包含的值x。你不需要一个let. 由于x := 0仅针对副作用进行评估,并返回类型unit(即没有什么用处),因此您可能熟悉;运算符,您可以使用它来将一堆副作用“语句”串在一起,这些“语句”评估为最后的结果一:x := 0; y' := y

于 2011-10-25T07:09:24.383 回答