Scala中try的递归调用

3

问题 1 ) 我正在尝试在 Scala 中从 YQL 中提取货币。下面提到的 getXML 接受 REST URL 并返回 xml 节点。在我的主代码中,如果失败后需要等待 10000 毫秒后再次调用 getXML。

请建议如何实现,因为我试图在失败代码中进行 getXML,但无法编译。

def getXML(url: String): Try[scala.xml.Node] =  
 {

 Try(XML.loadString(Source.fromURL(new URL(url)).mkString))

 }


val nodes = getXML(ccyurl) match {
  case Success(node) => node
  case Failure(f) => {
      Thread.sleep(10000)
      /****/
}  

问题2) 还有一个问题。我是新手,尤其是在Scala编程方面,所以有些困难。 我定义了一个函数

def exchangelookup(s :String): Try[String] = Try(exchange_currency_map(s))

它的使用方式如下所示,它是数组中的第4个项目。

exchangelookup(Cols(0).takeRight(3)) match {case Success(x) => x
                               case Failure(x) =>       FileParserlogger.error(x.getMessage()) } , //ExchangeCurrency 4

但是当我将其作为静态数组(4)中的另一个数组使用时,我会得到“类型不匹配;找到:Any,需要:String”

val fxconversion = fxconvertor(getexchange(nodes,static(10)),getexchange(nodes, exchange_to_real_ccy_map.getOrElse(static(4),static(4))))

提前感谢。

1个回答

3
您需要使用 recoverWith 来从 Failure 中恢复,并使用另一个 Try 。一个简单的用法如下所示:
def getXML(url: String): Try[scala.xml.Node] = {
    Try(XML.loadString(io.Source.fromURL(new URL(url)).mkString))
        .recoverWith {
            case _ => {Thread.sleep(10000); getXML(url)}
        }
}

然而,如果它永远不成功(我指的是直到由于递归太深而导致堆栈溢出),那么它将永远运行,这显然不是我们想要的。但是,很容易添加一个最大重试次数的计数器:

def getXML(url: String)(retries: Int): Try[scala.xml.Node] = {
    Try(XML.loadString(io.Source.fromURL(new URL(url)).mkString))
        .recoverWith {
            case _ if(retries > 0) => {
                Thread.sleep(10000)
                getXML(url)(retries - 1)
            }
        }
}

这种方法的另一个潜在问题是它是阻塞式的代码。根据您的用例,这可能没什么问题,但如果您的程序需要并发性能,则可以考虑使用Future代替Try。实现getXML的方式几乎完全相同,但使用方式会有所不同。


感谢m-z。这个函数的输出将是Try。我需要进行模式匹配才能仅获取成功,以便我获得scala.xml.Node吗?我之所以问这个问题,是因为这个函数的输出将被用作另一个接受scala.xml.Node的函数的输入。 - user3341078
是的,您将需要对此函数的返回值进行模式匹配或“映射”,因为仍然存在失败的可能性。 - Michael Zajac
还有一个最后的问题。我是编程新手,尤其是Scala,所以有点困难。 - user3341078
@user3341078 那应该是另一个问题。 - Michael Zajac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接