f# - 为什么不能将带有 byref 的函数直接转换为委托(delegate)?

标签 f# delegates ref byref

一般情况下,F#函数可以通过调用new DelegateType转换为委托(delegate)。并将函数作为参数传入。但是当委托(delegate)包含 byref参数,这是不可能的。例如代码:

type ActionByRef<'a> = delegate of 'a byref -> unit

let f (x:double byref) = 
    x <- 6.0

let x = ref 42.0
let d = new ActionByRef<_>(f)

无法编译,出现以下错误:

This function value is being used to construct a delegate type whose signature includes a byref argument. You must use an explicit lambda expression taking 1 arguments.



出现错误后,修改代码以使用
let d = new ActionByRef<_>(fun x -> f(&x))

作品。但我的问题是:为什么这是必要的?为什么 F# 不允许从命名函数转换到此委托(delegate),但从 lambda 转换很好?

我在研究 another question 时发现了这种行为.我意识到byref仅用于与其他 .Net 语言兼容。

最佳答案

我认为问题在于 byref<'T>不是 F# 中的实际类型 - 它看起来像一个类型(使语言更简单),但它被编译为标有 out 的参数旗帜。这意味着 byref<'T>只能在编译器实际可以使用 out 的地方使用旗帜。

函数值的问题在于您可以构造函数,例如通过部分应用:

let foo (n:int) (b:byref<int>) = 
  b <- n

当你通过 foo作为委托(delegate)构造函数的参数,它是部分应用程序(没有参数)的特定情况,但部分应用程序实际上需要构造一个新方法,然后将其交给委托(delegate):
type IntRefAction = delegate of byref<int> -> unit  

let ac = IntRefAction(foo 5)

编译器可以很聪明,并使用 byref 生成新方法参数(或 out 标志),然后通过引用将其传递给实际函数,但通常,当您不使用 fun ... -> ... 时,还会有其他编译器生成的方法句法。处理这会增加复杂性,我认为这是一个相对罕见的情况,所以 F# 编译器不会这样做,并要求你更明确......

关于f# - 为什么不能将带有 byref 的函数直接转换为委托(delegate)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9078689/

相关文章:

c# - 'ref' 和 'out' 关键字有什么区别?

c# - 实例化委托(delegate) (Func<T, T>) 的各种方式之间的区别?

f# - 类型提供者:如何重新生成?

.net - 实现领域驱动设计的功能方式

visual-studio - F# docker 应用程序 : A function labeled with the 'EntryPointAttribute' attribute must be the last declaration in the last file. ...?

jquery - 如何延迟 google 分析的 jquery 事件

ios - 为什么我们不用委托(delegate)对象来实例化委托(delegate)类呢?

c# - 为什么下面的代码编译没有错误?

clojure - 如何使用枚举/引用的实体 id 执行 Datomic 事务?

f# - F# 交互中的 Windows UI(UWP 或 8.1)