12

Is there any difference between this code:

    for(term <- term_array) {
        val list = hashmap.get(term)
        ...
    }

and:

    for(term <- term_array; val list = hashmap.get(term)) {
        ...
    }

Inside the loop I'm changing the hashmap with something like this

hashmap.put(term, string :: list)

While checking for the head of list it seems to be outdated somehow when using the second code snippet.

0

2 Answers 2

20

The difference between the two is, that the first one is a definition which is created by pattern matching and the second one is a value inside a function literal. See Programming in Scala, Section 23.1 For Expressions:

  for {
    p <- persons              // a generator
    n = p.name                // a definition
    if (n startsWith "To")    // a filter
  } yield n

You see the real difference when you compile sources with scalac -Xprint:typer <filename>.scala:

object X {
  val x1 = for (i <- (1 to 5); x = i*2) yield x
  val x2 = for (i <- (1 to 5)) yield { val x = i*2; x }
}

After code transforming by the compiler you will get something like this:

private[this] val x1: scala.collection.immutable.IndexedSeq[Int] =
  scala.this.Predef.intWrapper(1).to(5).map[(Int, Int), scala.collection.immutable.IndexedSeq[(Int, Int)]](((i: Int) => {
    val x: Int = i.*(2);
    scala.Tuple2.apply[Int, Int](i, x)
  }))(immutable.this.IndexedSeq.canBuildFrom[(Int, Int)]).map[Int, scala.collection.immutable.IndexedSeq[Int]]((
    (x$1: (Int, Int)) => (x$1: (Int, Int) @unchecked) match {
      case (_1: Int, _2: Int)(Int, Int)((i @ _), (x @ _)) => x
    }))(immutable.this.IndexedSeq.canBuildFrom[Int]);

private[this] val x2: scala.collection.immutable.IndexedSeq[Int] =
  scala.this.Predef.intWrapper(1).to(5).map[Int, scala.collection.immutable.IndexedSeq[Int]](((i: Int) => {
    val x: Int = i.*(2);
    x
  }))(immutable.this.IndexedSeq.canBuildFrom[Int]);

This can be simplified to:

val x1 = (1 to 5).map {i =>
    val x: Int = i * 2
    (i, x)
  }.map {
    case (i, x) => x
  }

val x2 = (1 to 5).map {i =>
    val x = i * 2
    x
  }
Sign up to request clarification or add additional context in comments.

3 Comments

Interesting. Could the transformation result be transformed into something more human readable?
@Suma not sure what you mean. The compiler output is valid Scala code (except some minor printing artifact issues). You can't get more high level or readable than that.
To make it easier to comprehend one could get rid of some valid, but not necessary parts, like type annotations, or canBuildFroms where not necessary, so that it looks more like something a human would write. I guess it is a bit mundane work, but perhaps it would make the core reason why the handling is different more obvious. I may try it later, if you do not think it is worth your effort.
8

Instantiating variables inside for loops makes sense if you want to use that variable the for statement, like:

for (i <- is; a = something; if (a)) {
   ...
}

And the reason why your list is outdated, is that this translates to a foreach call, such as:

term_array.foreach {
   term => val list= hashmap.get(term)
} foreach {
  ...
}

So when you reach ..., your hashmap has already been changed. The other example translates to:

term_array.foreach {
   term => val list= hashmap.get(term)
   ...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.