views:

351

answers:

2

I have the following variable series:

var series: List[FlotSerie] = List(
  new FlotSerie() {
    override val label = Full("Min")
  },
  new FlotSerie() {
    override val label = Full("Max")
  },
  new FlotSerie() {
    override val label = Full("Avg")
  }
)

Unfortunately, I am getting a compiler error with the following method, which takes a new data point and updates series with a new List[FlotSeries] based upon the new data and the old series.

def updateSeries(sample: Sample): List[FlotSerie] = {
  series = series.map(serie =>
    serie match {
      case item if item.label == Full("Min") => {
        new FlotSerie() {
          override val label = item.label
          override val data = (sample.timestamp.toDouble, sample.min) :: serie.data
        }
      }
      case item if item.label == Full("Max") => {
        new FlotSerie() {
          override val label = item.label
          override val data = (sample.timestamp.toDouble, sample.max) :: serie.data
        }
      }
      case item if item.label == Full("Avg") => {
        new FlotSerie() {
          override val label = item.label
          override val data = (sample.timestamp.toDouble, sample.avg) :: serie.data
        }
      }
    }
  )
}

The Scala compiler chokes on the reassignment because it finds a type mismatch:

error: type mismatch;
found   : Unit
required: List[net.liftweb.widgets.flot.FlotSerie]
   series = series.map(serie => serie match {

What am I doing wrong here? It seems like it should be returning a List[FlotSeries] that can be assigned to series. Since the compiler finds Unit I thought of how foreach always returns Unit, I am but the match operator returns the last value of the matched expression, not Unit.

A: 

remove series = you're assigned the map function to series and not returning anything.

Jonoabroad
+6  A: 

Assignments in Scala return Unit (aka Scala's not quite null null), unlike Ruby which returns the assigned value. Your method is attempting to return Unit instead of List[FlotSerie].

Add:

return series

to your method, or change it to return Unit.

You could also simplify your code using case classes and proper matching if it's appropriate:

  case class FlotSerie(label:Full, data:List[Tuple2[Double, Double]])
  var series: List[FlotSerie] = List( FlotSerie(Full("Min"), Nil), FlotSerie(Full("Max"), Nil), FlotSerie(Full("Avg"), Nil) )

  def updateSeries(sample: Sample): List[FlotSerie] = {
    series = series.map(serie => {
      serie.label match {
        case Full("Min") => FlotSerie(serie.label, (sample.timestamp.toDouble, sample.min) :: serie.data)
        case Full("Max") => FlotSerie(serie.label, (sample.timestamp.toDouble, sample.max) :: serie.data)
        case Full("Avg") => FlotSerie(serie.label, (sample.timestamp.toDouble, sample.avg) :: serie.data)
      }
    })
    return series
  }

I'm pretty new to Scala myself so YMMV.

Alex Neth
Thanks, Alex, the type error wasn't making it clear to me that the problem wasn't with my mapping but with the return value of the method. Thanks for reminding me that an assignment returns Unit. I wish it returned the assigned value!
pr1001
I've had cases where I wish it returned the assigned value, but then I stopped using var altogether and programming functionally and I'm much happier :) The reason is likely to do with avoid the = vs == bugs, and there are probably some syntax limitations that would place on other parts of the language.
Alex Neth