将 Span<T> 传递给函数时出现 F# 错误
F# error when piping Span<T> to a function
在下面的F#代码中,f1将Span作为输入,f2调用f1。
当参数通过管道而不是传递时,编译器会给出指示的错误。
let f1 (span: Span<byte>) = span.Length
let f2() =
let buf = [|0uy|].AsSpan()
buf |> f1 // FS0412
f1 buf // Ok
FS0412 A type instantiation involves a byref type. This is not permitted by the rules of Common IL
有没有办法将 Span 通过管道传输到 F# 函数中?
只是为了为什么添加一点颜色:
Byrefs 和 byref-like 类型与 functional-first 编程背道而驰。
这些类型需要将其整个生命周期都放在堆栈上,并附带一些允许运行时省略某些检查的编译器分析。这对性能非常有用。
创建函数时first-class,它涉及堆分配。基本上,它是一个带有 Invoke
方法的对象。在 F# 编译器中有几个优化尝试将 F# 函数转换为静态方法(大多数 F# 函数声明都是这样),但在很多情况下它们作为堆上的对象发出(有些你可以预测,有些你不能)。这意味着几件事:
- 您不能传递以 byref 或 byref-like 类型作为参数的函数
- 您不能使用 byref 或 byref-like 输入 lambda
- 您不能在内部函数中使用 byref 或 byref-like 类型
在某些情况下,这在技术上是可行的,但源代码中没有任何内容可以说明为什么在某些情况下可行,而在其他情况下则不行。原因很简单,“因为编译器需要将此函数作为对象发出”,这是完全不可预测的 non-uniform。一个proposed suggestion would help with this, but it's closed in favor of tweaks in the compiler and like this suggestion,从预测的角度估计应该不会太差
现在 |>
案例更有趣了,其他几个声明的函数也是如此 inline
。 |>
运算符的字面意思是将 higher-order 函数作为参数,因此自然不应支持它。但是因为它被定义为 inline
,它实际上可以工作,因为它只是一种优化。但是,这也可能要求您只能在 other inline
函数的上下文中使用它。您可能无法通过管道输入任何任意函数。
这就是为什么这不是一个错误,而是一个 by-design 行为,如果实施,将认真考虑增强:https://github.com/fsharp/fslang-suggestions/issues/688
在下面的F#代码中,f1将Span作为输入,f2调用f1。 当参数通过管道而不是传递时,编译器会给出指示的错误。
let f1 (span: Span<byte>) = span.Length
let f2() =
let buf = [|0uy|].AsSpan()
buf |> f1 // FS0412
f1 buf // Ok
FS0412 A type instantiation involves a byref type. This is not permitted by the rules of Common IL
有没有办法将 Span 通过管道传输到 F# 函数中?
只是为了为什么添加一点颜色:
Byrefs 和 byref-like 类型与 functional-first 编程背道而驰。
这些类型需要将其整个生命周期都放在堆栈上,并附带一些允许运行时省略某些检查的编译器分析。这对性能非常有用。
创建函数时first-class,它涉及堆分配。基本上,它是一个带有 Invoke
方法的对象。在 F# 编译器中有几个优化尝试将 F# 函数转换为静态方法(大多数 F# 函数声明都是这样),但在很多情况下它们作为堆上的对象发出(有些你可以预测,有些你不能)。这意味着几件事:
- 您不能传递以 byref 或 byref-like 类型作为参数的函数
- 您不能使用 byref 或 byref-like 输入 lambda
- 您不能在内部函数中使用 byref 或 byref-like 类型
在某些情况下,这在技术上是可行的,但源代码中没有任何内容可以说明为什么在某些情况下可行,而在其他情况下则不行。原因很简单,“因为编译器需要将此函数作为对象发出”,这是完全不可预测的 non-uniform。一个proposed suggestion would help with this, but it's closed in favor of tweaks in the compiler and like this suggestion,从预测的角度估计应该不会太差
现在 |>
案例更有趣了,其他几个声明的函数也是如此 inline
。 |>
运算符的字面意思是将 higher-order 函数作为参数,因此自然不应支持它。但是因为它被定义为 inline
,它实际上可以工作,因为它只是一种优化。但是,这也可能要求您只能在 other inline
函数的上下文中使用它。您可能无法通过管道输入任何任意函数。
这就是为什么这不是一个错误,而是一个 by-design 行为,如果实施,将认真考虑增强:https://github.com/fsharp/fslang-suggestions/issues/688