User1291
User1291

Reputation: 8189

Scala's wrong forward reference error

private def foo(a:A):B = a match{
    case A(...) =>
        val x = a.b //error: wrong forward reference a
        ...
}

Where b is not mentioned in A(...), if that matters.

I've tried my luck on Google, but I seem to find only posts of people having errors involving forward references but no explanation of what this particular error actually means.

Would appreciate it if somebody could help me out.

Upvotes: 15

Views: 18966

Answers (3)

Pandemonium
Pandemonium

Reputation: 8390

Here is an attempt to explain what @User1291 had not with his/her answer.

I'm new to Scala and Java so the answer wasn't obvious to me. I was surprised to run into this error in my (simplified) code:

object Main {
  val data = getData()
  def getUser() = {
     getUserFrom(data) // error: Wrong Forward Reference
  }
}

Wrong Forward Reference is equivalent to Java's Illegal Forward Reference, which is a fancy way of saying you can't reference a value that isn't known at compile time. In this case, getData() can only return value during run time, and referencing data gave this error.

When I tried changing the code to reference a known string, as expected the error went away:

object Main {
  val name = "PieOhPah"
  def getUser() = {
     getUserFrom(name)
  }
}

Another way is to close over the value with a function and access it from inside since functions are not evaluated until runtime:

object Main {
  val data = getData()
  def getUser(userData: UserData) = {
     getUserFrom(userData)
  }

  // Invoke the method later with `data`
  print(getUser(data).name) 
}

Upvotes: 5

User1291
User1291

Reputation: 8189

Well, don't I feel stupid now...

private def foo(a:A):B = a match{
    case A(...) =>
        val x = a.b //error: wrong forward reference a
        ...
        val a = ... //<-- THAT's the reason for the error
        ...
}

So a simple rename will resolve the issue:

private def foo(aa:A):B = aa match{
    case A(...) =>
        val x = aa.b
        ...
        val a = ...
        ...
}

Upvotes: 28

sarveshseri
sarveshseri

Reputation: 13985

The problem is that you are probably using pattern-matching in some wrong way. As... You have not provided complete code. I have no idea about what is that mistake.

I am sure there is a problem somewhere else as following code (which is almost same as what you have given ) works flawlessly,

scala> :pa
// Entering paste mode (ctrl-D to finish)

case class A( c: String ) {
  val b: String = c
}

def demoA( a: A ): String = a match {
  case A( iAmC ) => {
    val x = a.b
    x
  }
}


// Exiting paste mode, now interpreting.

defined class A
demoA: (a: A)String

scala> val anA = A( "sdfsd" )
anA: A = A(sdfsd)

scala> demoA( anA )
res3: String = sdfsd

So... basically if you have a case class like following,

case class A( b: String, c: String )

Now following would have worked.

private def foo( a:A ): B = a match{
  case A( iAmB, iAmC ) => {
    // iAmB and iAmC have values of a.b and a.c repectively
    ...
  }
}

In your case...your function clearly says that your a is an instance of A - def foo( a:A ) so... you really don't need to pattern match here.

private def foo( a:A ): B = {
  // Now class A should have member b and c
  val iAmB = a.b
  val iAmC = a.c
  ...
}

Upvotes: 1

Related Questions