gpt4 book ai didi

f# - 可变值和不可变值重定义有什么区别?

转载 作者:行者123 更新时间:2023-12-04 22:12:50 26 4
gpt4 key购买 nike

我读过 F# 中的值是不可变的。但是,我也遇到了重新定义值定义的概念,它影响了之前的定义。这与可变值有何不同?我问这不仅仅是作为一个理论结构,而且是否有任何关于何时使用可变值以及何时重新定义表达式的建议;或者如果有人可以指出后者不是惯用的 f#。

重新定义的基本示例:

let a = 1;;
a;; //1
let a = 2;;
a;; //2

更新1:

添加到下面的答案中,Fsharp interactive 在顶层的重新定义只允许在不同的终端中。以下内容也会在 fsi 中引发错误:
let a = 1
let a = 2;;

Error: Duplicate definition of value 'a'

另一方面,在 let 绑定(bind)中允许重新定义。

更新 2:
实际区别,闭包不能与可变变量一起使用:
let f =
let mutable a = 1
let g () = a //error
0
f;;

更新 3:

虽然我可以使用 refs 对副作用进行建模,例如:
let f =
let a = ref 1
let g = a
a:=2
let x = !g + !a
printfn "x: %i" x //4

f;;

除了使用闭包的差异之外,我看不出重定义和使用 mutable 关键字之间的实际差异,例如:
let f  =
let a = 1
let g = a
let a = 2
let x = g + a
printfn "x: %i" x //3

f;;

对比
let f =
let mutable a = 1
let g = a
a <-2
let x = g + a
printfn "x: %i" x //3
f;;

另一个思路:我不确定如何使用线程,但是(a)另一个线程可以在 let 绑定(bind)中改变可变变量的值,并且(b)另一个线程可以在一个中重新绑定(bind)/重新定义一个值名称让绑定(bind)。我当然在这里遗漏了一些东西。

更新 4:
最后一种情况的不同之处在于,突变仍然会发生在嵌套范围内,而嵌套范围内的重新定义/重新绑定(bind)将从外部范围“隐藏”定义。
let f =
let mutable a = 1
let g = a
if true then
a <-2
let x = g + a
printfn "x: %i" x //3

f;;

对比
let f =
let a = 1
let g = a
if true then
let a = 2
printfn "a: %i" a
let x = g + a
printfn "x: %i" x //2
f;;

最佳答案

我特别不熟悉 F#,但我可以回答“理论”部分。

改变一个对象是(或至少有可能)一个全局可见的副作用。任何其他引用同一对象的代码都将观察到这种变化。现在可以更改在程序中任何位置建立的依赖于对象值的任何属性。例如,如果您以影响其排序位置的方式更改该列表中引用的对象,则列表已排序的事实可能会呈现为错误。这可能是一个非常不明显和非本地的效果 - 处理排序列表的代码和执行突变的代码可能位于完全独立的库中(两者都没有直接依赖于另一个),仅通过长链调用连接(其中一些可能是其他代码设置的闭包)。如果您相当广泛地使用突变,那么这两个位置之间甚至可能没有直接的调用链链接,这个可变对象最终被传递给该突变代码的事实可能取决于所执行的特定操作序列由程序出到目前为止。

另一方面,将局部变量从一个不可变值重新绑定(bind)到另一个,在技术上可能仍被视为“副作用”(取决于语言的确切语义),但它是一个相当本地化的变量。因为它只影响名称,而不影响之前或之后的值,所以对象来自哪里或在此之后它们将去往哪里都没有关系。它只改变访问该名称的其他代码位的含义;您必须仔细检查受此影响​​的代码的地方仅限于名称的范围。这是一种很容易保留在方法/函数/其他内部的副作用,因此从外部角度来看,该函数仍然没有副作用(纯粹;引用透明) - 实际上没有捕获的闭包名称而不是值我相信这种本地重新绑定(bind)不可能成为外部可见的副作用。

关于f# - 可变值和不可变值重定义有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20324625/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com