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