为什么 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),绑定到值的标识符是值本身,所以你不能改变它。
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),绑定到值的标识符是值本身,所以你不能改变它。