Skip to content

Lazy value returns different result on second call #7748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
scabug opened this issue Aug 13, 2013 · 3 comments
Closed

Lazy value returns different result on second call #7748

scabug opened this issue Aug 13, 2013 · 3 comments
Assignees

Comments

@scabug
Copy link

scabug commented Aug 13, 2013

The following code returns a different result on the second call. It seems that the second call returns only the calculated percents without passing it to the prettifyPercents method.

import scala.util.Try

object Bug {
  def main(args: Array[String]) {
    val results = Map(1 -> 1, 2 -> 1 , 3 -> 1, 4 -> 4)
    val survey = Survey(results)

    println(survey.percents)
    println(survey.percents)
  }
}

case class Survey(results: Map[Int, Int]) {

  lazy val percents: Map[Int, Int] = prettifyPercents {
    val total = results.foldLeft(0)(_+_._2)
    for ((key, value) <- results) yield key -> Try(math.round(value * 100.0 / total).toInt).getOrElse(0)
  }

  private def prettifyPercents(percents: Map[Int, Int]) = {
    percents.foldLeft(0)(_+_._2) match {
      case 100 => percents
      case total: Int => {
        var remainder = 100 - total
        percents.mapValues { percent =>
          if (percent != 0 && remainder > 0) {
            remainder = remainder - 1
            percent + 1
          } else if (percent != 0 && remainder < 0) {
            remainder = remainder + 1
            percent - 1
          } else {
            percent
          }
        }
      }
    }
  }
}

Expected output:

Map(1 -> 15, 2 -> 14, 3 -> 14, 4 -> 57)
Map(1 -> 15, 2 -> 14, 3 -> 14, 4 -> 57)

Actual output:

Map(1 -> 15, 2 -> 14, 3 -> 14, 4 -> 57)
Map(1 -> 14, 2 -> 14, 3 -> 14, 4 -> 57)
@scabug
Copy link
Author

scabug commented Aug 13, 2013

Imported From: https://issues.scala-lang.org/browse/SI-7748?orig=1
Reporter: Christian Kaps (akkie)
Affected Versions: 2.11.0-M4

@scabug
Copy link
Author

scabug commented Aug 13, 2013

@paulp said:
Don't use mapValues. Duplicate of #4776.

@scabug scabug closed this as completed Aug 13, 2013
@scabug
Copy link
Author

scabug commented Aug 13, 2013

@som-snytt said:
I was going to suggest A View to a Shill but I see you might also be interested in Captured by Closures.

If it were somehow desirable to do it this way, you could:

  lazy val percents: Map[Int, Int] = prettifyPercents {
    val total = results.valuesIterator.sum
    for ((key, value) <- results) yield key -> Try(math.round(value * 100.0 / total).toInt).getOrElse(0)
  }.view.force //.iterator.toMap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants