为什么 MonoGame 的 Rectangle class 字段在 F# 中不可变?

Why are MonoGame's Rectangle class fields immutable in F#?

    let rect = new Rectangle(x, y, sprite.Width, sprite.Height)
    rect.X <- 888

第二行在 F# 中失败,但在 C# 中赋值有效。我不知道为什么。

Rectangle 是结构而不是 class。如果用 mutable:

标记该值,则可以使该行按预期工作
let mutable rect = new Rectangle(10, 21, 10, 21)
rect.X <- 888

这实际上非常有趣,因为与 C# 相比,F# 使结构的 value-type 语义更加可见。

rect.X <- 888 并没有真正改变字段,而是用修改了 X 字段的结构的新值更新 rect。所以你可以想象它相当于 rect <- { rect with X = 888 }。到那时,编译器为什么要在那里看到 mutable 就很清楚了。

我想知道为什么 F# 设计者不禁止结构的赋值语法并使用类似于记录语法的东西。可能他们不想让它与 C# 相比有太大的不同。

编译器可能会说,

A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...'

在 F# 中,let 创建一个不可变变量(即值)。编译器通过不让你改变它来强制执行这一点。您必须编写 let mutable 以获得与您在 C# 中的等效的变量声明。

请注意,如果 Rectangle 是引用类型,F# 不会报错,因为您修改的是值引用的内容,而不是值本身。在值类型的情况下(如 Mono 的 Rectangle),绑定到值的标识符是值本身,所以你不能改变它。