F# 从 CollectionsMarshal.GetValueRefOrAddDefault 返回 byref

发布于 2025-01-15 04:43:55 字数 763 浏览 1 评论 0原文

我试图获取从 CollectionMarshal.GetValueRefOrAddDefault 方法返回的 byref 。现在 t 是一个 int 但我想要 byref

open System.Runtime.InteropServices
let d = System.Collections.Generic.Dictionary<int, int>()

let t, _ = CollectionsMarshal.GetValueRefOrAddDefault (d, 1)

F# 文档说要在方法调用前添加 & ,但编译器会返回错误。

let t, _ = &CollectionsMarshal.GetValueRefOrAddDefault (d, 1)
// Error:
// Cannot take the address of the value returned from the expression.
// Assign the returned value to a let-bound value before taking the address.
// F# Compiler3236

I am trying to get the byref<int> that is returned from the CollectionMarshal.GetValueRefOrAddDefault method. Right now t is an int but I am wanting the byref<int>.

open System.Runtime.InteropServices
let d = System.Collections.Generic.Dictionary<int, int>()

let t, _ = CollectionsMarshal.GetValueRefOrAddDefault (d, 1)

The F# docs say to prepend a & to the method call but then the compiler returns an error.

let t, _ = &CollectionsMarshal.GetValueRefOrAddDefault (d, 1)
// Error:
// Cannot take the address of the value returned from the expression.
// Assign the returned value to a let-bound value before taking the address.
// F# Compiler3236

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猫烠⑼条掵仅有一顆心 2025-01-22 04:43:55

这里有一些示例代码来说明解决方案:

open System.Runtime.InteropServices

// without this you get a warning about the byref-typed `v` being a top-level value in a module
type Blah() = 
    let d = System.Collections.Generic.Dictionary<int, int>()
    let mutable t = Unchecked.defaultof<_>
    let v = &CollectionsMarshal.GetValueRefOrAddDefault (d, 1, &t)

这里发生的情况是,您试图对编译器试图加糖的内容进行去糖(隐式可变占位符参数),但在我看来,编译器加糖的方式存在差距。您可以提出一个合理的论点,即 let struct(wasAdded, value) = CollectionsMarshal.GetValueRefOrAddDefault(d, 1) 可能是合理的脱糖,因为没有分配等。

无论如何,在您的示例中让我们看看您尝试调用的成员的签名:

GetValueRefOrAddDefault : System.Collections.Generic.Dictionary<'Key, 'Value> * 'Key * byref<bool> -> byref<'Value>

编译器有一个方法模式,该模式具有以 out/byref 值结尾并返回 byref 值的参数列表:它将执行所有操作为您记账。我的意思是,它将为您初始化 let mutable x = Unchecked.defaultof<_> 单元格,使用这些单元格的引用值调用该方法,并为您提供最终答案。

因为你想做快速的事情,所以你只需要自己包装而不是让编译器脱糖。

Here's some sample code to illustrate a solution:

open System.Runtime.InteropServices

// without this you get a warning about the byref-typed `v` being a top-level value in a module
type Blah() = 
    let d = System.Collections.Generic.Dictionary<int, int>()
    let mutable t = Unchecked.defaultof<_>
    let v = &CollectionsMarshal.GetValueRefOrAddDefault (d, 1, &t)

What's happening here is that you're trying to de-sugar what the compiler is trying to sugar (implicit mutable placeholder parameters), but there's a gap here IMO in the ways the compiler sugars things. You could make a reasonable argument that let struct(wasAdded, value) = CollectionsMarshal.GetValueRefOrAddDefault(d, 1) could be a reasonable desugaring, due to no allocations, etc, etc.

Anyway, in your example let's look at the signature of the member you're trying to invoke:

GetValueRefOrAddDefault : System.Collections.Generic.Dictionary<'Key, 'Value> * 'Key * byref<bool> -> byref<'Value>

The compiler has a pattern for methods that have parameter lists that end with out/byref values and return byref values: it will do all of the bookkeeping for you. By this I mean it will initialize the let mutable x = Unchecked.defaultof<_> cells for you, call the method with the ref values to those cells, and give you the final answers.

Because you want to do fast things, you just need to do that wrapping yourself instead of letting the compiler desugar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文