在我發布此評論后https://github.com/fsharp/fslang-suggestions/issues/349#issuecomment-1124206512 我仍然覺得我錯過了......
為方便讀者,此處轉載示例代碼:
let spanOfOptString(os: Option<string>) =
match os with Some(s) -> s.AsSpan()
| None -> raise(Exception())
錯誤 FS0412:型別實體化涉及 byref 型別。Common IL 的規則不允許這樣做。
因此,F#raise像Exception -> 'afree 'a(“OCaml 方式”)一樣鍵入了一個不回傳函式,并且型別變數碰巧系結到了 byref 型別ReadOnlySpan,這是非法的。我覺得我因為我沒有犯下的罪行而受到了懲罰......
我可以找到類似的解決方法
let checkedSpanOfString(os: Option<string>) =
match os with Some(s) -> s.AsSpan()
| None -> raise(Exception()) // 'a = unit
ReadOnlySpan.Empty // both arms: ReadOnlySpan<char>
https://sharplab.io/#gist:32b520574fde97de8d7389ab04f64bc4
但恕我直言,這有點難看。而且我認為我們不應該期望等效.Empty于所有byref 型別的東西?(我認為我從未使用過除 ( ReadOnly)之外的任何其他 byref 型別Span/Memory但那是另一回事)
雖然 F# 核心團隊似乎并沒有朝著將底層型別引入語言的方向發展(這可能是一個明智的工程決策),
但有沒有人有更好的替代方案來完成這項作業?
更新
@chadnt 的答案可以行內得到
let checkedSpanOfString(os: Option<string>) =
let s = match os with Some(s) -> s
| None -> raise(Exception())
s.AsSpan()
https://sharplab.io/#gist:a5eab805c539c45048b4072fa7b096c5
它的 IL 看起來比我的原始版本簡單得多
uj5u.com熱心網友回復:
看起來首先分配字串值似乎可以解決它。
open System
let valueOrRaise = function
| Some v -> v
| None -> raise(Exception())
let checkedSpanOfString (os: string option) =
let s = valueOrRaise os
s.AsSpan()
https://sharplab.io/#gist:2ca959f498be87f1b52212182af237b4
在 FSI 中:
> (checkedSpanOfString (Some "foo")).ToString();;
val it: string = "foo"
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/477883.html
上一篇:泛型引數放置之間的打字稿差異
下一篇:在C#中將類重構為多層泛型類
