F# &引用;闭包无法捕获可变变量”;是不是给了我糟糕的一天
我正在使用一个F# &引用;闭包无法捕获可变变量”;是不是给了我糟糕的一天,f#,F#,我正在使用一个externDLL,它有一系列例程返回ReturnCodeenum,因此我编写了以下帮助函数来记录所有错误: let mutable LastError = ReturnCode.OK let mutable LastReturnCode = ReturnCode.OK let mutable TotalErrors = 0 let Run (call: unit -> ReturnCode) = LastReturnCode <- call() if Las
extern
DLL,它有一系列例程返回ReturnCode
enum,因此我编写了以下帮助函数来记录所有错误:
let mutable LastError = ReturnCode.OK
let mutable LastReturnCode = ReturnCode.OK
let mutable TotalErrors = 0
let Run (call: unit -> ReturnCode) =
LastReturnCode <- call()
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
编译器给了我一个“闭包无法捕获可变变量”错误。除了到处内联Run
之外,我还能做什么?这在C#中效果很好
(下面的extern声明示例)
[]
外部返回代码EdsCreateEvfImageRef(int-inStreamHandle,[]int&outevImageHandle);
标准解决方案是使用引用-代码变为
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &(!evfImageHandle)))
!evfImageHandle
let Run (call: ReturnCode) =
LastReturnCode <- call
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
但是,由于编译器需要,这将不起作用!evfImageHandle
是可变的,而不是可变的
我认为真正的解决方案是更改Run
函数,这样它就不需要闭包,而只需要返回值——在这种情况下,它至少可以工作。然后代码变为
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, &(!evfImageHandle)))
!evfImageHandle
let Run (call: ReturnCode) =
LastReturnCode <- call
if LastReturnCode <> ReturnCode.OK then
LastError <- LastReturnCode
TotalErrors <- TotalErrors + 1
或者是更老套的解决方案。使用数组成员是可变的,并且可以被闭包捕获的事实来执行此操作
let CreateEvfImageRef (streamHandle: int) =
let evfImageHandle = [|0|]
Run (fun () -> EdsCreateEvfImageRef (streamHandle, &(evfImageHandle.[0])) )
evfImageHandle.[0]
您应该仍然能够使用
ref
类型,但在将引用传递给函数时不需要写入&
符号-编译器将自动执行此操作:
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, evfImageHandle))
!evfImageHandle
常量表达式的无效变异。考虑将表达式复制到一个可改变的局部,例如“让可变x=……”。现在应该可以正常工作了吗?我想你也忘了去掉
&
?但这仍然让我感到类型不匹配。需要byref ref,但给定int ref,类型“byref”与类型“int”不匹配。我添加了我的extern声明作为示例。@lobsterism-我想不出比消除闭包或创建用作参数的伪数组更优雅的解决方案。类型不匹配。需要byref ref,但给定int ref,类型“byref”与类型“int”不匹配这在fsi中对F#2.0或3.0都不起作用,使用以下外部定义[]外部内部EdsCreateEvfImageRef(int-inStreamHandle,[]int&outevImageHandle)代码>(与lobsterism的错误相同)类型定向转换仅应用于类型成员,我怀疑这里Extern是一个模块,而不是类型
let CreateEvfImageRef (streamHandle: int) =
let mutable evfImageHandle = ref 0
Run (fun () -> Extern.EdsCreateEvfImageRef (streamHandle, evfImageHandle))
!evfImageHandle