aaron02
aaron02

Reputation: 338

Scala code during compilation runs into error: recursive value info needs type

I'm trying to overwrite a list variable declared before in the Scala code, but when I try to compile the JAR using it, I keep running into the compiler error: error: recursive value info needs type

def extract_FileContent = udf((file_contents: String) => {

  val info = (file_contents.replace("\",\"", "     ")
    .replace("\"", "")
    .replaceAll("    ", "|")
    .replaceAll(" : \r\n", " : empty\r\n")
    .replaceAll("\r\n", "|")
    .replaceAll(" : ", "|")
    .replaceAll(": ", "|")
    .split("\\|")
    .map(x => x.trim.replaceAll(" -", ""))
    .filterNot(s => s == ""))
  // type info = Array[String]

  if (info.toList(42) == "Start Archive Record") {
    val info = info.take(42) ++ info.drop(50) \\ recursive error here
    }
}

Upvotes: 0

Views: 2181

Answers (2)

Dima
Dima

Reputation: 40500

You you define info twice. The definition inside the if statement, shadows the first defintion - basically, info on the left, and right side refer to the same (new) variable, not to the one you defined before, that's why it thinks, it's recursive.

Solution? Just give it a different name ... or, in this case, you don't actually have to name it at all:

val info = file_contents.replace ...
 ...
if (info(42) == "Start Archive Record") { // don't do `.toList` here, it's not only redundant, but actually makes things worse
  info.take(42) ++ info.drop(50)
} else info

Upvotes: 3

FerranJr
FerranJr

Reputation: 332

Hi @aaron02 by quickly checking your code there are a couple things that are wrong, one of them the one you claim.

val keyword defines a constant, and your code is trying to override the constant "info" based on that condition... if you wanted that, you should probably use a var.

On the other one, within the if you are defining a constant based on it itself... this is the recursivity you are seeing the error for... the compiler helps you with type inference but on this case it requrires that you specify the type.

The following would work on isolation, but together on your code the compiler will tell you about your code trying to reassign a val.

val info: Array[String] = info.take(42) ++ info.drop(50)

hopefully this put some light in your coding.

update:

This snippet might be close to what you want:

def extract_FileContent = (file_contents: String) => {

  var info = file_contents.replace("\",\"", "     ")
    .replace("\"", "")
    .replaceAll("    ", "|")
    .replaceAll(" : \r\n", " : empty\r\n")
    .replaceAll("\r\n", "|")
    .replaceAll(" : ", "|")
    .replaceAll(": ", "|")
    .split("\\|")
    .map(x => x.trim.replaceAll(" -", ""))
    .filterNot(s => s == "")

  if (info.toList(42) == "Start Archive Record") {
    info = info.take(42) ++ info.drop(50) // recursive error here
  }
  info // This as last statement will mean we return the Array[String], otherwise we were returning a Unit (side effect only)
}

Upvotes: 1

Related Questions