Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用尾部递归函数时try/catch不起作用_Scala_Apache Spark - Fatal编程技术网

Scala 使用尾部递归函数时try/catch不起作用

Scala 使用尾部递归函数时try/catch不起作用,scala,apache-spark,Scala,Apache Spark,我正在构建一个尾部递归函数,它读取多个hdfs路径并将所有路径合并到一个数据帧中。只要所有路径都存在,函数就可以正常工作,如果不存在,函数将失败,并且没有完成连接确实存在的路径的数据。为了解决这个问题,我尝试使用try/catch来处理错误,但没有成功 错误显示:无法优化@tailrec注释的方法循环:它包含一个不在尾部位置的递归调用 我的职能是: def getRangeData(toOdate: String, numMonths: Int, pathRoot: String, Column

我正在构建一个尾部递归函数,它读取多个hdfs路径并将所有路径合并到一个数据帧中。只要所有路径都存在,函数就可以正常工作,如果不存在,函数将失败,并且没有完成连接确实存在的路径的数据。为了解决这个问题,我尝试使用try/catch来处理错误,但没有成功

错误显示:无法优化@tailrec注释的方法循环:它包含一个不在尾部位置的递归调用

我的职能是:

def getRangeData(toOdate: String, numMonths: Int, pathRoot: String, ColumnsTable: List[String]): DataFrame = {

    val dataFrameNull = spark.createDataFrame(spark.sparkContext.emptyRDD[Row],
      StructType((ColumnsTable :+ "odate").map(columnName => StructField(columnName, StringType, true))))

    val rangePeriod = getRangeDate(numMonths, toOdate)

    @tailrec
    def unionRangeData(rangePeriod: List[LocalDate], pathRoot: String, df: DataFrame = dataFrameNull): DataFrame = {
      try {
        if (rangePeriod.isEmpty) {
          df
        }
        else {
          val month = "%02d".format(rangePeriod.head.getMonthValue)
          val year = rangePeriod.head.getYear
          val odate = rangePeriod.head.toString

          val path = s"${pathRoot}/partition_data_year_id=${year}/partition_data_month_id=${month}"
          val columns = ColumnsTable.map(columnName => trim(col(columnName)).as(columnName))
          val dfTemporal = spark.read.parquet(path).select(columns: _*).withColumn("odate", lit(odate).cast("date"))

          unionRangeData(rangePeriod.tail, pathRoot, df.union(dfTemporal))
        }
      } catch {
        case e: Exception =>
          logger.error("path not exist")
          dataFrameNull
      }
    }

    unionRangeData(rangePeriod, pathRoot)
  }

  def getRangeDate(numMonths: Int, toOdate: String, listDate: List[LocalDate] = List()): List[LocalDate] = {
    if (numMonths == 0) {
      listDate
    }
    else {
      getRangeDate(numMonths - 1, toOdate, LocalDate.parse(toOdate).plusMonths(1).minusMonths(numMonths) :: listDate)
    }
  }

首先,非常感谢您的帮助。

我建议您完全从函数中删除
try-catch
构造,并在
getRangeData
底部的调用站点使用它

或者,您也可以使用
scala.util.Try
包装调用:
Try(unionRangeData(rangePeriod,pathRoot))
,并使用其组合符之一执行日志记录或在错误情况下提供默认值

解释Scala编译器无法在try catch内执行尾部调用优化的相关帖子:

我建议您完全从函数中删除
try-catch
构造,并在
getRangeData
底部的调用站点使用它

或者,您也可以使用
scala.util.Try
包装调用:
Try(unionRangeData(rangePeriod,pathRoot))
,并使用其组合符之一执行日志记录或在错误情况下提供默认值

解释Scala编译器无法在try catch内执行尾部调用优化的相关帖子:

在处理Spark数据集时,我真的不认为担心尾部重复有多大意义。这感觉更像是担心火车的轮胎压力。我不明白你的意思,解释一下你的selftail递归是一种通过递归函数调用避免不必要的堆栈累积的技术。大多数spark操作(transform)产生一个表示计算图的AST,它只是一个数据结构。然后,仅当执行消耗操作时,才对该计算图进行优化和计算。这种计算也发生在分布式环境中。这意味着尾部递归的整个概念实际上(不应该)与Spark应用程序无关,如果你曾经需要担心Spark应用程序中的尾部递归,那么你做的事情确实是错误的,就像在火车上安装轮胎,然后担心轮胎压力。在处理Spark数据集时,我认为担心尾部递归没有多大意义。这感觉更像是担心火车的轮胎压力。我不明白你的意思,解释一下你的selftail递归是一种通过递归函数调用避免不必要的堆栈累积的技术。大多数spark操作(transform)产生一个表示计算图的AST,它只是一个数据结构。然后,仅当执行消耗操作时,才对该计算图进行优化和计算。这种计算也发生在分布式环境中。这意味着尾部递归的整个概念实际上(不应该)与Spark应用程序无关,如果您需要担心Spark应用程序中的尾部递归,那么您所做的事情实际上是错误的,类似于在火车上安装轮胎,然后担心轮胎压力。