Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Programming languages SML:“;“幕后”;不可变变量的定义?_Programming Languages_Immutability_Sml - Fatal编程技术网

Programming languages SML:“;“幕后”;不可变变量的定义?

Programming languages SML:“;“幕后”;不可变变量的定义?,programming-languages,immutability,sml,Programming Languages,Immutability,Sml,我有一个关于标准ML(SML)的问题。我已经读到SML具有不变的变量。当一个值绑定到一个变量时,它是终身设置的,不能更改 我的问题是:它是如何“幕后”运作的;i、 在记忆中。例如,如果运行以下程序: vala=5; vala=a+1; 解释器会在内存中为'new'a分配一个新的位置吗 这个想法有什么好处?感觉它不如C这样的编程语言有效。变量在SML中确实不同,就像变量在数学中不同一样。也就是说,一般来说,他们在不同的情况下可以代表不同的价值观。比如说, fun f x = let val

我有一个关于标准ML(SML)的问题。我已经读到SML具有不变的变量。当一个值绑定到一个变量时,它是终身设置的,不能更改

我的问题是:它是如何“幕后”运作的;i、 在记忆中。例如,如果运行以下程序:

vala=5;
vala=a+1;
解释器会在内存中为'new'
a
分配一个新的位置吗


这个想法有什么好处?感觉它不如C这样的编程语言有效。

变量在SML中确实不同,就像变量在数学中不同一样。也就是说,一般来说,他们在不同的情况下可以代表不同的价值观。比如说,

fun f x =
  let val a = x + 1 in ... end
fun factorial 0 = 1
  | factorial n = n * factorial (n - 1)
这里,
a
的值随
x
的变化而变化。这是“变量”一词在数学中的原意

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

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

let
  val r = ref 1
in
  f (!r);
  r := 2;
  f (!r)
end
最后,您的示例演示了一种完全不同的现象,即声明的阴影。这不是ML独有的,您的程序与C中的以下程序类似:

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


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

变量在SML中确实不同,就像变量在数学中不同一样。也就是说,一般来说,他们在不同的情况下可以代表不同的价值观。比如说,

fun f x =
  let val a = x + 1 in ... end
fun factorial 0 = 1
  | factorial n = n * factorial (n - 1)
这里,
a
的值随
x
的变化而变化。这是“变量”一词在数学中的原意

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

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

let
  val r = ref 1
in
  f (!r);
  r := 2;
  f (!r)
end
最后,您的示例演示了一种完全不同的现象,即声明的阴影。这不是ML独有的,您的程序与C中的以下程序类似:

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

因为这会使程序对人类读者更加混乱,所以不建议在两种语言的程序中使用阴影。您总是可以通过重命名其中一个变量来避免它

解释器会在内存中为'new'
a
分配一个新的位置吗

是的,没错

SML有两种功能:值绑定和可变引用(例如C中的变量)

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

在这里,
a
的值不变,它被另一个
a
隐藏,从而创建一个新的范围,隐藏旧的
a
。因此,如果使用旧的
a
和阴影
a
,则旧的
a
的用法不会改变。一个更具说明性的例子:

val a = 5
fun f x = x + a
val a = 10
val b = f 1  (* = 6, not 11 *)
这个想法有什么好处

在您的示例中有两个想法(值绑定和阴影),因此我想确保我回答了正确的问题:

  • 值绑定而不是可变引用意味着命名值在其生命周期内不会更改。这是很好的,因为对代码进行推理更容易。要找到绑定的值,您可以转到它的定义,您将知道它从那时起从未更改过值

    您可以通过向函数提供值来改变值绑定。你可以把它看作是数学意义上的一个变量,但不是可变的引用。因此,它们仅在作为函数输入参数的上下文中发生变化。比如说,

    fun f x =
      let val a = x + 1 in ... end
    
    fun factorial 0 = 1
      | factorial n = n * factorial (n - 1)
    
    这里
    n
    是一个值绑定和数学意义上的变量,但不是可变引用

  • 阴影表示命名值可以被同名的其他命名值隐藏。这不是一个很好的特性,因为它可能会引起混乱。正如给事物取个好名字很重要一样,不给两个事物取相同的名字也同样重要

    许多函数式编程语言不允许阴影

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

    f(X) ->
        A = 5,
        A = 6,
        X + A.
    
    f :: Int -> Int
    f x = x + a
      where
        a = 5
        a = 6
    
    在Haskell中,以下是一个错误:

    f(X) ->
        A = 5,
        A = 6,
        X + A.
    
    f :: Int -> Int
    f x = x + a
      where
        a = 5
        a = 6
    
  • SML确实有变量,但它们不会变化

    对,值绑定也是如此,它在SML中最常见。“不可变变量”可能会引起混淆,因为“变量”可以表示“可变引用”和“函数参数”

    同时具有函数式和命令式语言特性的SML也具有可变引用:

    let
      val r = ref 1
    in
      f (!r);
      r := 2;
      f (!r)
    end
    
    这里
    ref:'a->'a ref
    创建一个引用并
    !:'a ref->'a
    取消对其的引用

    这些都和在美国一样危险