SML 中的值绑定?

Value Bindings in SML?

有人可以帮忙吗。我不知道这里的评估顺序以及我们如何获得 "ans" 的值。例如在第一个例子中没有 y 的值,我不确定这个 returns 是一对还是调用 x ! (fn y => y x)。如果你能跟踪每个表达式,那将是非常有帮助的。

val x = 1
val f = (fn y => y x)
val x = 7
val g = (fn y => x - y)
val ans = f g

val ans = 6 : int

=====================================
fun f p =
let
val x = 3
val y = 4
val (z,w) = p
in
(z (w y)) + x
end
val x = 1
val y = 2
val ans = f((fn z => x + z), (fn x => x + x + 0))

val ans = 12 : int

有几件事有助于使此类问题更加清晰 当尝试理解外星函数时 Lexical scoping 有效。

  1. 在不修改程序的情况下,在参数和return值中添加类型,编译器会告诉你如果你弄错了...
  2. 用命名函数替换匿名函数。
  3. 重命名具有相同名称但引用不同词法范围的变量绑定。
  4. 删除只使用一次的变量绑定。

将值绑定到名称实际上并不执行任何计算, 所以只是为了 reader 的利益,如果它没有做那项工作的话 它只是用来混淆,然后一定要删除它。

fun f (y1 : int -> 'a) = y1 1 : 'a;
fun g (y2 : int) = 7 - y2 : int;
val ans : int = f g;

所以 g 作为 f 的参数给出,f 调用 g 给它参数 x,其值为 1,使得 y2 = 1,g 减去 7 - 1 returning 6。 g 的 return 值是一个 int,因此 f 的 'a 当 g 应用于它时的类型是一个 int。

对于第二个稍微清理一下,我将匿名 fn 提取到它们自己的命名值中并调用 f (foo, bar) 以使其更具可读性...

fun f p =
 let val x = 3
     val y = 4
     val (z, w) = p
  in (z (w y)) + x end
fun foo z = z + 1;
fun bar x = x * 2;
val ans = f(foo, bar);

最后,我们可以摆脱只使用一次的 let 值 并将 (z,w) = p 替换为仅 (z, w) 作为函数的参数,这应该更容易理解

fun f (z, w) = (z (w 4)) + 3
fun foo z = z + 1;
fun bar x = x * 2;
val ans = f(foo, bar);
val ans = ((4 * 2) + 1) + 3