Why can't a function with byref be converted directly to delegate?

岁酱吖の 提交于 2019-12-19 07:23:47

问题


Under normal circumstances, F# functions can be converted to delegates by calling new DelegateType and passing in the function as an argument. But when the delegate contains byref parameter, this is not possible directly. For example the code:

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)

won't compile, giving the following error:

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.

Following the error, modifying the code to use

let d = new ActionByRef<_>(fun x -> f(&x))

works. But my question is: why is this necessary? Why won't F# allow the conversion from named function to this delegate, but conversion from lambda is fine?

I came upon this behavior when researching another question. I realize byref is meant only for compatibility with other .Net languages.


回答1:


I think the problem is that byref<'T> is not an actual type in F# - it looks like a type (to make the language simpler), but it gets compiled to a parameter marked with the out flag. This means that byref<'T> can be only used in a place where the compiler can actually use the out flag.

The problem with function values is that you can construct function e.g. by partial application:

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

When you pass foo as an argument to a delegate constructor, it is a specific case of partial application (with no arguments), but partial application actually needs to construct a new method and then give that to the delegate:

type IntRefAction = delegate of byref<int> -> unit  

let ac = IntRefAction(foo 5)

The compiler could be clever and generate new method with byref parameter (or out flag) and then pass that by reference to the actual function, but in general, there will be other compiler-generated method when you don't use the fun ... -> ... syntax. Handling this would add complexity and I think that's a relatively rare case, so the F# compiler doesn't do that and asks you to be more explicit...



来源:https://stackoverflow.com/questions/9078689/why-cant-a-function-with-byref-be-converted-directly-to-delegate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!