Reputation: 16501
In the code below, does it matter where I put the query
object (within the loop, or outside)? For readability, I would prefer this 1st version:
class MyClass {
db withSession {
names.foreach { name =>
val query = MyEntity.createFinderBy(_.name) <----------
query.list(text).foreach(res =>
doSomething
}
}
}
}
But isn't this 2nd version better?
class MyClass {
db withSession {
val query = MyEntity.createFinderBy(_.name) <----------
names.foreach { name =>
query.list(text).foreach(res =>
doSomething
}
}
}
}
Or even?
class MyClass {
val query = MyEntity.createFinderBy(_.name) <----------
db withSession {
names.foreach { name =>
query.list(text).foreach(res =>
doSomething
}
}
}
}
In Java, I would put it in a static final field at the top of the class...
Upvotes: 1
Views: 212
Reputation: 53348
scalac does not (can not) optimize your code because it doesn't use an effect system. This makes it almost impossible for scalac to care if an optimization can break code. For example, if MyEntity.createFinderBy(_.name)
is not pure (maybe it increments a counter which counts the number of accesses) it will make a change if it is executed once or in each iteration.
In such cases I can suggest to change the position of the function literal:
scala> 1 to 3 foreach {x => println("x"); println(x)}
x
1
x
2
x
3
scala> 1 to 3 foreach {println("x"); x => println(x)}
x
1
2
3
In the second example a block returning a function passed to foreach is created (after executing other expressions), whereas in the former one, the whole block is a single function.
Upvotes: 2
Reputation: 51109
No it does not, because in the first example you specifically told it to call createFinderBy
(and also list
) for each element. There's no guarantee that those methods will return the same value each time (i.e. are referentially transparent), so the values can't be memoized or the code optimized to the second or third examples.
It would be a nice feature if you could annotate methods as such, or if the compiler could work it out, but at the moment it doesn't.
As an aside, you could change the createFinderBy
method so that it stores values in a mutable.Map
cache and returns values using the getOrElseUpdate
method, which returns a cached value if your query is already in the map, or else calculates the query and caches it.
Upvotes: 2