gpt4 book ai didi

f# - F# 中的无参数异步工作流是否应该包装在函数中?

转载 作者:行者123 更新时间:2023-12-05 00:30:50 25 4
gpt4 key购买 nike

如果我在 F# 中有一个异步无参数工作流,是否有必要和/或惯用地将它变成一个函数,还是最好保留为原始值?

例如,如果我想定义getRemoteCounterAfterOneSec,轮询一些远程计数器源,应该是

let getRemoteCounterAfterOneSec = 
async {
do! Async.Sleep 1000
return! ...
}

let getRemoteCounterAfterOneSec () = 
async {
do! Async.Sleep 1000
return! ...
}

似乎他们应该做同样的事情,只是后者有一个不必要的参数。但是我已经看到这在各种代码中都是以两种方式完成的。我还看到了行为最终不同的地方:如果使用 MailboxProcessor 并执行

let myFunc = mailboxProc.PostAndAsyncReply(fun reply -> GetCount reply)
async {
let! count1 = myFunc
let! count2 = myFunc
}

然后邮箱处理器只被调用一次;第二次它只返回在前一次调用中计算的相同值。但是,如果 myFunc 是一个函数,那么它会像您预期的那样调用 mailboxProcessor 两次。

let myFunc() = mailboxProc.PostAndAsyncReply(fun reply -> GetCount reply)
async {
let! count1 = myFunc()
let! count2 = myFunc()
}

这是实现中的错误吗?这是怎么回事,什么是惯用语?

最佳答案

当涉及到您自己定义的普通异步时,添加 () 没有任何效果(好吧,这意味着 描述计算 的异步是重复构造的,但没有实际作用)。

有时我写它只是为了让我的代码更容易理解,或者当异步是递归的时候(因为当你有递归值时你会收到警告)。所以,下面的内容没问题,但它会给你一个警告:

let rec loop = 
async {
do! Async.Sleep 1000
if 1 > 2 then return 1
else return! loop }

PostAndAsyncReply 方法的写法有点不同 - 名称试图反射(reflect)这一点。正常的 F# 异步方法被命名为 AsyncFooBar。这个有 PostAndAsyncFooBar 来指示它首先 发布然后异步等待,类似于:

let PostAndAsyncWait () =
post(message)
async { let! sth = wait ()
return sth }

所以,这里它实际上是在异步之外发布的 - 这让您可以调用该函数,即使您(在语法上)在 async block 之外。这个名字试图对此非常明确。
(但我个人更喜欢它是否全部在异步内部,即 AsyncPostAndWait)。

关于f# - F# 中的无参数异步工作流是否应该包装在函数中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29970505/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com