Unexpected Error: Reassignment to val

2019-09-08 01:13发布

问题:

I get this error when compiling:

Compilation error: reassignment to val

I think this seems obvious, but when looking at my code I can't find why this doesn't works.

Here is the sample of code where the error happens, from my ConferenceController.scala:

def createConfWithPrivacy(confId: Long, groupId: Option[Long]) = ForcedAuthentication 
{implicit request =>
    Future {
      val user = request.user.get
      var newConf = Conference.findById(confId).get
      if(groupId.isDefined){
        newConf.forGroup = LabGroup.findById(groupId.get)  <- there it is
        Conference.updateForGroup(newConf)
      }
      ...
    }
}

The variables in Conference.scala are declared like following:

case class Conference (
    id         : Long,
    title      : String,
    abstr      : String,
    speaker    : Speaker,
    startDate  : DateTime,
    length     : Duration,
    organizedBy: Lab,
    location   : Location,
    accepted   : Boolean,
    acceptCode : Option[String],
    priv       : Boolean,
    forGroup   : Option[LabGroup]=None
) {... Functions ...}

The functions called is from the LabGroup.scala file, I know this one works:

def findById(id: Long): Option[LabGroup] = DB.withConnection { implicit  c =>
    SQL("SELECT * FROM LabGroup WHERE id = {id}")
      .on("id" -> id)
      .as(labGroupParser.singleOpt)
  }

But I don't understand why this error happens because newConf is a var and normally the Conference.forGroup should be one too.

If you see something done wrong, please tell me.

Thanks for help.

回答1:

When you instantiate a case class like you have done, every member of it is a val by default. You have to explicitly tell Scala that you want to have it as a var. Just do it like that:

case class Conference (
    id         : Long,
    ...
    var forGroup   : Option[LabGroup]=None
)

EDIT:
As Régis Jean-Gilles posted in his comment, a more idiomatic way of changing the value of forGroup would be this code:

newConf.forGroup = newConf.copy(forGroup = LabGroup.findById(groupId.get))

This would leave forGroup as a Value and is a better [functional] way of doing "reassignments".



回答2:

var newConf = Conference.findById(confId).get defines a variable newConf. This variable can be reassigned. However, the forGroup value of newConf is still just that, a value, and as such it cannot be changed.

If you want to update forGroup for newConf, then it needs to be declared variable, which you can do with :

case class Conference (
    id         : Long,
    // ...
    var forGroup   : Option[LabGroup]=None
)


标签: scala