Reputation: 105
I'm a new beginner to Scala, and I'm now learning the for statements. I read this tutorial http://joelabrahamsson.com/learning-scala-part-six-if-statements-and-loops/
And in this tutorial, there is a example,
for (person: Person <- people
if !person.female;
name = person.name;
if name.contains("Ewing"))
println(name)
If compare this for loop to the for loop in Java, is it like
for(person: people) {
if (!person.female) {
String name = person.name;
if (name.contains("Ewing"))
println(name)
}
}
or like this:
for(person: people) {
String name = person.name;
if (!person.female && name.contains("Ewing")) {
println(name)
}
}
Are the operations (in this example, name = person.name;) executed if the first filter condition "if !person.female;" is not satisfied?
Thanks!
Upvotes: 2
Views: 1946
Reputation: 31724
To see what the scala compiler generates, compile as scalac -Xprint:typer
. It gives:
people.withFilter(((check$ifrefutable$1: typer.Person) => check$ifrefutable$1: @scala.unchecked match {
case (person @ (_: Person)) => true
case _ => false
}))
//filter is acting as your if-clause
.withFilter(((person: Person) => person.<female: error>.unary_!)).map(((person: Person) => {
val name = person.name;
scala.Tuple2(person, name)
}))
//Your next if-clause
.withFilter(((x$1) => x$1: @scala.unchecked match {
case scala.Tuple2((person @ (_: Person)), (name @ _)) => name.contains("Ewing")
}))
//Print each of them
.foreach(((x$2) => x$2: @scala.unchecked match {
case scala.Tuple2((person @ (_: Person)), (name @ _)) => println(name)
}))
}
}
So in short it as acting as your first mentioned case. But as a concept, it is always recommended to think for-comprehensions as a mapping of map
, foreach
, flatmap
etc.
This is because in many cases while dealing with yield
you will need to manage types and thinking in terms of foreach
and filter
(which in java sense is foreach
and if
) will not cover all cases. For example, consider below:
scala> for(x <- Option(1);
| u <- scala.util.Left(2)
| ) yield (x,u)
<console>:9: error: value map is not a member of scala.util.Left[Int,Nothing]
u <- scala.util.Left(2)
Above for
comprehension uses flatmap
and map
. Thinking in terms of Java for
loops (foreach
basically`) will not help in finding the reason.
Upvotes: 1
Reputation: 613
I think it would not evaluate the follows expressions as it is a common implementation to do so with AND conditions. You can see here
http://www.scala-lang.org/api/current/index.html#scala.Boolean
That scala also has this short circuit implementation when using &&
Upvotes: 0
Reputation: 52681
Try it out!
for{
x <- 1 to 10
if x % 3 == 0
y = println(f"x=$x")
if x % 2 == 0
} {
println(x)
}
prints:
x=3
x=6
x=9
6
So this means that the y=
line is happening before the second if
filter.
Upvotes: 1
Reputation: 16412
Scala for
comprehension unfolds into combination of map
, flatmap
and filter
. In your case if
is actually a filter for all values that appear before it in this "iteration" of the "loop". So if if
condition is not satisfied the loop will skip this iteration, so your Java for
loops behave the same way as Scala example.
For example try this in REPL:
scala> val l = List(1, 2, 3, 4, 5, 6)
l: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> for (i <- l
| if(i%2 == 0))
| println(i)
2
4
6
scala>
This is equivalent to:
l.filter(_%2 == 0).foreach(println)
Upvotes: 1