【问题标题】:return position in an async block, in F#在 F# 中返回异步块中的位置
【发布时间】:2021-06-13 02:06:11
【问题描述】:

我有以下代码:

let private SendOk (payload: 'a) : WebPart =
    payload |> Json.serialize |> OK >=> Writers.setMimeType "application/json"


let getBTCBalance (addresses: string list) : Async<WebPart> =
    async {
        try
            let! reply = blockExplorer.GetMultiAddressAsync addresses |> Async.AwaitTask
            return reply.Addresses |> Seq.map (fun x -> x.FinalBalance.GetBtc()) |> SendOk
        with
        | :? ArgumentNullException as ex -> return BAD_REQUEST    ex.Message
        | ex                             -> return INTERNAL_ERROR ex.Message
    }

它使用的是 Suave Web 服务器,两个路径(正常和错误)都返回一个 WebPart 类型的对象。

如果我尝试移动 return 语句来包装其他所有内容,我会得到以下代码:

let getBTCBalance (addresses: string list) : Async<WebPart> =
    async {
        return ( 
            try
                let! reply = blockExplorer.GetMultiAddressAsync addresses |> Async.AwaitTask
                reply.Addresses |> Seq.map (fun x -> x.FinalBalance.GetBtc()) |> SendOk
            with
            | :? ArgumentNullException as ex -> BAD_REQUEST    ex.Message
            | ex                             -> INTERNAL_ERROR ex.Message
        )
    }

try/with 块应该返回一个 WebPart 对象,我认为用一个返回来包装它会更好读。

编译器不同意:

[FS0750] 此构造只能在计算表达式中使用

我不明白为什么会这样。谁能给我解释一下?

【问题讨论】:

    标签: asynchronous f# computation-expression suave


    【解决方案1】:

    那是因为您使用的是let!

    let! 在异步计算中创建一个断点,将代码一分为二,第二部分作为延续传递(请参阅this answer 了解其工作原理)。

    您不能将整个内容作为单个表达式返回,因为实际上它不是单个表达式,它只是看起来像一个。实际上,您的函数在 let! 之后结束,并开始一个完全独立的函数。

    这是您问题的简化版本:

    let f = async {
      return (let! x = doSomethingAsync)
    }
    

    这能让您更好地了解问题所在吗?

    【讨论】:

    • 好的,是的,现在很清楚了。谢谢!既然让!确实是句法肯定,它肯定是在隐藏这一点。
    猜你喜欢
    • 2021-10-25
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多