2011-05-09 225 views
3

我目前正在玩斯卡拉斯无阻塞期货又名。承诺。我努力使下面的函数尾递归:尾递归和斯卡拉承诺

@tailrec 
private def repeat(res: Promise[I]):Promise[I] = 
    res map p flatMap { 
    (b:Boolean) => 
     if(b) repeat(res flatMap f) else res 
    } 

其中pI=>Boolean型和f谓词是 型I=>Promise[I]并发功能。

该方法在没有注释的情况下编译。

任何提示?谢谢

回答

4

你的方法根本不是递归的。 res是一个可能在另一个线程中运行的计算。就您的方法而言,res map p flatMap f将立即返回承诺。重现到repeat将发生在另一个过程中。

稍微简洁些,Promise是继续monad,flatMap调用会自动转换为继续传递样式。

1

虽然这看起来是尾递归的,因为调用在代码中只出现一次,但您有多个递归调用 - 您的集合中的每个元素都有一个调用。至少这就是编译器所看到的。 (假设这是某个集合上的flatMap;我不知道p会返回什么)

您将递归作为匿名函数传递给某个地方。没有人知道它将被执行多久。

+0

感谢您的回答。但是你有没有想过我可以如何解决这个问题而不被阻塞? – paradigmatic 2011-05-09 15:09:18

+2

对不起,但我不熟悉scalaz。我试图找出代码中的'p'调用是失败的。你能想到你的代码使用while循环的程序版本吗?如果这是不可能的,那就不可能有tco。 – ziggystar 2011-05-09 15:49:49

+1

“,您的集合中的每个元素都有一个,至少这是编译器看到的。”是不正确的,恕我直言:'Promise'不是一个集合,编译器只看到一个调用(不在尾部位置)。然而,第二段既正确又足以解释为什么这不是尾递归。 – 2011-05-09 19:04:40