Programming languages SML:“;“幕后”;不可变变量的定义?
我有一个关于标准ML(SML)的问题。我已经读到SML具有不变的变量。当一个值绑定到一个变量时,它是终身设置的,不能更改 我的问题是:它是如何“幕后”运作的;i、 在记忆中。例如,如果运行以下程序: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
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
是一个值绑定和数学意义上的变量,但不是可变引用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
let
val r = ref 1
in
f (!r);
r := 2;
f (!r)
end
这里ref:'a->'a ref
创建一个引用并!:'a ref->'a
取消对其的引用
这些都和在美国一样危险