新的F#开发人员,长期的C#开发人员。作为学习F#的练习,我正在研究Eric Lippert关于图形着色的系列,从他的C#转换为F#。我目前正在研究part two。
原始的C#在博客文章中-到目前为止,这是F#的翻译-但无法编译:
type BitSet = struct
val bits : int
private new(b) = { bits = b }
static member Empty = BitSet(0)
member this.Contains (item:int) = (this.bits &&& (1<<< item)) <> 0
member this.Add (item:int) = BitSet(this.bits ||| (1 <<< item))
member this.Remove (item:int) = BitSet(this.bits &&& ~~~(1<<<item))
member this.Bits = seq {
for item in 0..31 do
if this.Contains(item) then
yield item
}
end
这会产生非常神秘的错误“错误FS0406:Byref类型的变量'this'以无效方式使用。Byref无法被闭包捕获或传递给内部函数”,该定义来自Bits:seq
奇怪的是,将关键字“struct”更改为“class”会得到有效的代码。从C#的角度来看,这似乎是胡说八道,但是我敢肯定背后有一个正当的理由。问题是-我应该如何编写Bits函数?为了使之有意义,我需要了解什么基本的F#原理?
最佳答案
我认为问题在于,创建了this
引用作为对该结构体当前值的引用,以便您可以修改该结构体(如果需要并且该结构体是可变的)。
这会导致seq { .. }
内部出现问题,因为这会在另一个类中生成代码,因此编译器无法将引用传递给“this”实例。
如果为this
值分配一个普通的局部变量,则该代码可以正常工作:
member this.Bits =
let self = this
seq {
for item in 0..31 do
if self.Contains(item) then
yield item
}
作为样式问题-我可能会使用隐式构造函数,这会使代码短一些。与显式的
Struct
语法相比,我也更喜欢struct .. end
属性,但是这两者都只是样式问题(我敢肯定其他人会有不同的偏好)。您可能会发现它作为替代或比较有用:[<Struct>]
type BitSet private (bits:int) =
static member Empty = BitSet(0)
member this.Contains (item:int) = (bits &&& (1<<< item)) <> 0
member this.Add (item:int) = BitSet(bits ||| (1 <<< item))
member this.Remove (item:int) = BitSet(bits &&& ~~~(1<<<item))
member this.Bits =
let self = this
seq {
for item in 0..31 do
if self.Contains(item) then
yield item
}
关于class - 引用 'this'的F#结构成员导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41452698/