对于Froto项目(Google Protobuf in F#),我试图更新从'a ref
对象到传递值byref<'a>
的性能的反序列化代码。在F#中,是否可以将引用传递给可变默认值作为参数?
但是,下面的代码失败在hydrator &element field
行:
type Field = TypeA | TypeB | Etc
let hydrateRepeated
(hydrator:byref<'a> -> Field -> unit)
(result:byref<'a list>)
(field:Field) =
let mutable element = Unchecked.defaultof<'a>
hydrator &element field
result <- element :: result
错误FS0421:变量“元素”的地址不能在这一点上
使用有什么我能做到让代码在不改变hydrator
参数签名的情况下工作吗?
我很清楚我可以使用hydrator:'a ref -> Field -> unit
并让事情发挥作用。但是,目标是支持反序列化到record
类型,而无需在每次记录反序列化时在堆上创建一堆ref
对象。
请注意,以下代码是完全合法的,并且与上面的hydrator
函数声明具有相同的签名,所以我不清楚问题是什么。
let assign (result:byref<'a>) (x:'a) =
result <- x
let thisWorks() =
let mutable v = Unchecked.defaultof<int>
assign &v 5
printfn "%A" v
我认为这是一个编译器bug,甚至允许'hydrator'的签名。你不能有一个'byref <_>'作为F#函数类型的一部分,因为在CLR级别上需要类似于'FSharpFunc,...>和'byref's的东西是不合法的类型参数。 –
kvb
你应该做的是创建一个新的委托类型,它需要一个byref参数并使用它(类似于'byrefAction <'a,'b> =委托的byref <'a> *'b - >单位'然后'hydrator:byrefAction <'a,Field>')。那么就没有必要诉诸'ref'。 – kvb
关于编译器的错误行为,请参阅https://github.com/Microsoft/visualfsharp/issues/819以获取有关相关问题的集合。 – kvb