实际上,变量在SML中不变是什么意思?

时间:2019-02-20 00:57:31

标签: programming-languages sml

我对SML语言有疑问。我了解到SML确实有变量,但它们没有变化。当值和变量有界时,它们将永久存在并且无法更改。我的问题是它在内存中又如何“在幕后”工作。例如,如果我运行以下程序:

val a = 5;
val a = a + 1;

解释器是否会在内存中为'new'a分配一个新位置?

这个想法有什么好处?感觉比C这样的PL效率低。

2 个答案:

答案 0 :(得分:0)

变量在SML中确实有所不同,就像变量在数学中一样。也就是说,它们在不同情况下通常代表不同的价值。例如,

fun f x =
  let val a = x + 1 in ... end

此处,a的值随x的不同而不同。这是数学中“变量”一词的本义。

您不能做的是变异一个变量。在给定范围内,相同变量将始终代表相同值。将不可变性设置为默认值有很多优点,例如,它可以防止整个类的错误,并且对程序进行推理要容易得多,尤其是在涉及嵌套函数时。

可以仍然有突变,但是在ML中,这是一个独立的概念,更明确。您需要使用参考:

let
  val r = ref 1
in
  f (!r);
  r := 2;
  f (!r)
end

最后,您的示例演示了一种完全不同的现象,即声明的 shadowing 。那不是ML独有的,您的程序类似于C中的以下内容:

{
  const int a = 5;
  {
    const int a = a + 1;
  }
}

唯一真正的区别是,在C中,在第二个声明的右侧使用a使其递归地引用(尚未定义)第二个a,而在SML声明中是默认情况下是非递归的,因此右侧的a引用第一个声明。

因为它会使程序对人类读者更加混乱,所以不建议在两种语言中都不要在程序中使用阴影。您始终可以通过重命名变量之一来避免这种情况。

答案 1 :(得分:0)

val a = 5
val a = a + 1
     

解释器是否会在内存中为'new'a分配一个新位置?

是的。

SML有两件事,值绑定可变引用(因为变量在例如C中)。

您描述的是值绑定,它们的值不能在同一范围内变化。

此处a的值不会变化,它被另一个a 阴影遮盖,并使用旧的{{ 1}}隐藏。因此,如果您使用旧的a shadow a,则旧的a的用法不会改变。更具说明性的示例:

a
  

这个想法有什么好处?

您的示例中有两个想法(值绑定 shadowing ),所以我想确保回答正确的问题:

  1. 值绑定而不是可变引用意味着命名值在生命周期中不会发生变化。这很好,因为这样就可以更轻松地进行代码推理了。要查找绑定的值,可以转到其定义,然后您将知道该绑定从那时以来从未更改过值。

    您可以通过向函数输入值来使值绑定有所不同。您可以将其视为数学意义上的变量,而不是可变引用。因此,它们仅在作为函数的输入参数的上下文中有所不同。例如,

    val a = 5
    fun f x = x + a
    val a = 10
    val b = f 1  (* = 6, not 11 *)
    

    此处fun factorial 0 = 1 | factorial n = n * factorial (n - 1) 是一个值绑定和一个变量,但不是可变引用

  2. Shadowing 意味着命名值可以被相同名称的其他命名值隐藏。这并不是一个好功能,因为它可能会引起混乱。就像为事物命名很重要一样,不要给两个名称相同的事物同样重要。

    许多功能性编程语言都不允许 shadowing

    例如,在Erlang中,这是一个错误:

    n

    在Haskell中,以下是错误:

    f(X) ->
        A = 5,
        A = 6,
        X + A.
    
  

SML确实具有变量,但它们没有变化

对,因此值绑定正确,这是SML中最常见的值。 “不变变量”可能会引起混淆,因为“变量”可能意味着“可变参考”和“功能参数”。

同时具有功能性和命令性语言功能的

SML也确实具有可变引用

f :: Int -> Int
f x = x + a
  where
    a = 5
    a = 6

此处val a = ref 5 fun f x = x + !a val _ = a := 10 val b = f 1 (* 11, not 6 *) 创建引用,ref : 'a -> 'a ref取消引用。

这些危险与其他语言一样危险;可能更少,因为您不会偶然混合使用! : 'a ref -> 'a'a,因为类型系统会引发错误。从语法上讲,它们有点不切实际,但这应该提醒您,请警惕其用法。 :-)