如何正确地将嵌套的f#代码转换为异步表单

时间:2015-09-19 14:23:08

标签: asynchronous f#

我正在翻译所有f#代码以使用异步。我发现它比预期的更难,我想知道是否有更好的方法或者我错过了什么。

采取以下两个功能:

let test1() =
        let y = 
                let x = 
                        let z = f()
                        5 + z
                x + 6
        y + 3

let test2() =
        let z = f ()
        let x = 5 + z
        let y = x + 6
        y + 3

这些函数完全等效,但我的代码恰好采用test1的风格。

似乎编写为test1的代码转换为异步代价非常昂贵。例如,假设函数f()变为异步:

let f () =
        async{
                return 3
        }

问题是如何翻译test1和test2。事实证明test2很容易修复:

let test2Async() =
        async{
        let! z = f ()
        let x = 5 + z
        let y = x + 6
        return y + 3
        }

你只需输入一个“async {}”,一个“!”和一个“回归”。

但是如果你对test1做同样的事情,它就不会编译:

let test1AsyncWrong() =
        async{
        let y = 
                let x = 
                        let! z = f() // ERROR HERE: we are not in a computation expression, so I can't use !
                        5 + z
                x + 6
        return y + 3
        }

据我所知,您需要做的是正确翻译test1:

let test1AsyncRight() =
        async{
        let! y = 
                async{
                let! x = 
                        async{
                        let! z = f()
                        return 5 + z
                        }
                return x + 6
                }
        return y + 3
        }

请注意,我需要输入async {} 三次,再加上“!”三次并“返回”三次。

这似乎是一种不必要且违反直觉的并发症。感觉有什么不对劲。如果必须这样做,翻译这样的代码需要几天时间。

我错过了什么吗?这是怎么回事?谢谢你的帮助。

1 个答案:

答案 0 :(得分:3)

我不认为将async嵌套在另一个async中的方法更好。但它可能更糟糕,想象一下如果没有计算工作流程就可以。

我重构" asyncified"代码摆脱嵌套。所以对于你的例子,我有类似的东西 - 一个对async一无所知的常规函数​​,以及只关心将各个部分组合在一起的let test1 z = let y = let x = 5 + z x + 6 y + 3 let test1Async() = async{ let! z = f() return test1 z } 版本。 / p>

f

这当然是一个过于简单的例子。通常情况下,您有asyncs取决于某些参数,并且只是将其拉出其上下文可能是不可能的。在这种情况下,我会尝试重构逻辑以适应它,而不会在原始代码上撒上asyncs。收集运行let test () = async { let inputs = figureOutInputs() let! results = doAsyncStuff inputs return processResults results } ,运行它们并将结果作为单独步骤处理所需的所有信息。

interface Expression {
    int getValue();
}

class Constant implements Expression {
    private int value;
    public int getValue() {
        return value;
    }
}

class Operation implements Expression {
    private Expression operand1;
    private Operator operator;
    private Expression operand2;
    public int getValue() {
        return operator.apply(operand1, operand2);
    }
}

这样你可以限制传染扩散太多;)