在以下 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# 函式中?
uj5u.com熱心網友回復:
只是為為什么添加更多顏色:
Byrefs 和類似 byref 的型別與功能優先編程背道而馳。
這些型別的整個生命周期都必須在堆疊上,并附帶一些編譯器分析,允許運行時省略一些檢查。這對性能非常有用。
當一個函式成為第一類時,它涉及到一個堆分配。Invoke基本上,它是一個帶有方法的物件。在 F# 編譯器中,有幾個優化嘗試將 F# 函式轉換為靜態方法(大多數 F# 函式宣告都是這樣的),但在許多情況下它們作為堆上的物件發出(有些你可以預測,有些你不能)。這意味著幾件事:
- 您不能傳遞一個將 byref 或類似 byref 的型別作為引數的函式
- 您不能在 lambda 中使用 byref 或類似 byref 的型別
- 您不能在內部函式中使用 byref 或類似 byref 的型別
在某些情況下,這在技術上是可行的,但源代碼中沒有任何內容可以說明為什么在某些情況下它是可能的,而在其他情況下則不然。原因很簡單,“因為編譯器需要將此函式作為物件發出”,這是完全不可預測且不統一的。一個提議的建議會對此有所幫助,但它已關閉以支持編譯器中的調整,并且喜歡這個建議,從可預測性的角度來看,這估計可能不會太糟糕。
現在|>情況更有趣了,其他幾個宣告的函式也是如此inline。運算子在|>字面上被定義為接受一個高階函式作為引數,所以自然不應該支持它。但是因為它被定義為inline,它實際上可以作業,因為它只是一個優化。但是,這也可能要求您只能在其他 inline功能的背景關系中使用它。您可能無法通過管道進入任何任意函式。
這就是為什么這不是一個錯誤,而是一個設計行為,如果它被實施,將需要認真考慮增強:https ://github.com/fsharp/fslang-suggestions/issues/688
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/439510.html
上一篇:不支持WPF中的可視狀態管理器
