Reputation: 1023
I have flowing structure one the package in my project:
mypackage/
package1/
...
package.scala
package2/
...
package.scala
package3/
...
package.scala
In package1/package.scala:
package object package1 {
val checkMap = Map("a" -> 1)
}
In package2/package.scala:
package object package2 {
val checkMap = Map("b" -> 2)
}
In package3/package.scala:
package object package3 {
val checkMap = Map("c" -> 3)
}
(I have simplified the actual code for the demonstration)
In other place my project I have this stupid code:
class CheckThis(packageName: String) {
var checkerMap = Map[String, Int]()
if (packageName == "package1"){
import com.some.some_prj.mypackage.package1.checkMap
checkerMap = check
} else if (packageName == "package2"){
import com.some.some_prj.mypackage.package2.checkMap
checkerMap = check
} else if (packageName == "package3"){
import com.some.some_prj.mypackage.package3.checkMap
checkerMap = check
def checker(val: String) = checkerMap.getOrElse(val, -1)
}
Now I need to add package4
, package5
, package6
... into mypackage
How use parameter in import statement?
Something like:
class CheckThis(packageName: String) {
import com.some.some_prj.mypackage.$packageName.{checkMap => checkerMap}
Or maybe there is a functional variant of import statement:
class CheckThis(packageName: String) {
val checkerMap:Map[String, Int] = import(s"com.some.some_prj.mypackage.$packageName.checkMap"}
Upvotes: 1
Views: 121
Reputation: 53348
In Scala it is not possible to generate import statements at runtime, all imports are resolved at compile time. For such an usecase it is easy to use a Map that contains a value to determine the code that should be executed (or even the code itself in form of a function):
// R is the return value
val m = Map[String, () => R] = {
val block1 = { () =>
doSomething()
doSomethingElse()
ret
}
val block2 = { () =>
doSomething()
doSomethingElse()
ret2
}
Map("package1" -> block1, "package2" -> block2)
}
val f = m(packageName)
// execute code here and use return value if necessarey
val ret = f()
Upvotes: 1
Reputation: 9705
No, not without resorting to macros or manipulating classloading, either of which would probably be an overkill for whatever you're doing.
Here's the full subgrammar for import statements from Chapter 4.7 of the SLS:
Import ::= ‘ import ’ ImportExpr {‘,’ ImportExpr}
ImportExpr ::= StableId ‘.’ (id | ‘_’ | ImportSelectors)
ImportSelectors ::= ‘{’ {ImportSelector ‘,’}
(ImportSelector | ‘_’) ‘}’
ImportSelector ::= id [‘=>’ id | ‘=>’ ‘_’]
As you can see there is not way to insert something parametrized there. You have to either stick to your original boilerplate-based approach, or use an alternative (the choice of which depending on how your "checker" code structure actually looks like).
Upvotes: 2