OCaml中的不可变变量

OCaml中的不可变变量,ocaml,Ocaml,我正在学习OCaml,对变量的不变性有点困惑。根据我正在读的书,变量是不可变的。到目前为止还不错,但我究竟为什么能这样做: let foo = 42 let foo = 4242 我遗漏了什么???名称foo首先绑定到一个不可变值42,然后它被反弹到另一个不可变值4242。您甚至可以将相同的名称绑定到不同类型的变量。在OCaml中,我们讨论的不是变量的易变性,而是值的易变性。例如,如果将foo绑定到一个值数组,则该数组的名称相同,但绑定到一个可变数据,因此变量的值可以随时间变化。最后,每个新绑

我正在学习OCaml,对变量的不变性有点困惑。根据我正在读的书,变量是不可变的。到目前为止还不错,但我究竟为什么能这样做:

let foo = 42
let foo = 4242

我遗漏了什么???

名称
foo
首先绑定到一个不可变值
42
,然后它被反弹到另一个不可变值
4242
。您甚至可以将相同的名称绑定到不同类型的变量。在OCaml中,我们讨论的不是变量的易变性,而是值的易变性。例如,如果将
foo
绑定到一个值数组,则该数组的名称相同,但绑定到一个可变数据,因此变量的值可以随时间变化。最后,每个新绑定只隐藏上一个绑定,因此原始foo仍然绑定到
42
,但它是不可见的,并且将被垃圾收集

也许一个小例子可以澄清这个想法:

let example () = 
  let foo = 42     in (* 1 *)
  let foo = 4242   in (* 2 *)
  let foo = [|42|] in (* 3 *)
  foo.(0) <- 56       (* 4 *)
1
2
行中,我们只是将变量
foo
绑定到两个不同的值。在第
3行
中,我们将其绑定到一个包含一个元素的数组。在第4行,我们更改了值,foo仍然绑定到相同的值,但该值包含不同的数据


我希望我没有让你更加困惑;)

我认为最好的解释方法是举个例子。考虑此代码(在OcAML RePL中执行):

其中:

  • 创建包含
    42
    的可变引用,并将其绑定到名称
    foo
  • 创建一个函数
    return\u foo()
    ,该函数返回绑定到
    foo
    的引用中存储的值
  • 在绑定到
    foo
    的引用中存储
    24
  • 调用
    return\u foo()
    函数,该函数返回
    24

  • let
    的通常形式是
    let。。。在
    表达式中,定义变量绑定,该绑定仅存在于let的主体内部。
    let
    的主体是一个新的作用域

    let x = 42 in (* body here *)
    
    这里,
    let
    的“主体”是一个不同于外部的新范围,所有外部变量都带有一个附加的局部变量
    x
    ,该局部变量仅在该
    let
    主体中定义

    现在您讨论的是让s位于文件的顶层。它们在语法上看起来有点不同(在中没有
    ),但实际上它们是相同的,“body”是文件的其余部分。因此,在这里,您可以将文件中
    let
    之后的其余部分视为一个新范围,其中
    x
    是该范围的局部变量。因此,您的代码与此等效:

    let foo = 42 in (
      let foo = 4242 in (
        (* rest of file *)
      )
    )
    
    在这里,您的内部
    绑定一个局部变量,该局部变量与外部范围中已经存在的变量同名。那没关系。您正在内部作用域中绑定一个新变量。如果它恰好与外部作用域中的变量同名,那么内部作用域中引用该名称的代码将引用最内部的绑定。然而,这两个变量是完全独立的

    在类似C的语言中,应该是这样的:

    {
        const int foo = 42;
        {
            const int foo = 4242;
            // rest of code here
        }
    }
    

    看到了吗?这里没有任何变量赋值。

    您没有更改上一个变量的值,只是创建了一个新的foo,它的名称隐藏了上一个变量
    let x = 42 in (* body here *)
    
    let foo = 42 in (
      let foo = 4242 in (
        (* rest of file *)
      )
    )
    
    {
        const int foo = 42;
        {
            const int foo = 4242;
            // rest of code here
        }
    }