如何在import语句中使用参数?

时间:2014-02-15 11:35:39

标签: scala import

我的项目包中有一个流程结构:

mypackage/
    package1/
       ...
       package.scala
    package2/
       ...
       package.scala
    package3/
       ...
       package.scala

在package1 / package.scala中:

package object package1 {
    val checkMap = Map("a" -> 1)
}

在package2 / package.scala中:

package object package2 {
    val checkMap = Map("b" -> 2)
}

在package3 / package.scala中:

package object package3 {
    val checkMap = Map("c" -> 3)
}

(我已经简化了演示的实际代码)

在其他地方我的项目我有这个愚蠢的代码:

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)

}

现在我需要将package4package5package6 ...添加到mypackage

如何在import语句中使用参数?

类似的东西:

class CheckThis(packageName: String) {

    import com.some.some_prj.mypackage.$packageName.{checkMap => checkerMap}

或者可能存在import语句的功能变体:

class CheckThis(packageName: String) {

    val checkerMap:Map[String, Int] = import(s"com.some.some_prj.mypackage.$packageName.checkMap"}

2 个答案:

答案 0 :(得分:2)

不,不是没有诉诸宏或操纵类加载,无论你做什么都可能是一种过度杀伤

以下是the SLS第4.7章中导入语句的完整子语法:

Import ::=           ‘ import ’ ImportExpr {‘,’ ImportExpr}
ImportExpr ::=       StableId ‘.’ (id | ‘_’ | ImportSelectors)
ImportSelectors ::=  ‘{’ {ImportSelector ‘,’}
                        (ImportSelector | ‘_’) ‘}’
ImportSelector ::=   id [‘=>’ id | ‘=>’ ‘_’]

正如您所看到的那样,无法插入参数化的东西。您必须坚持使用原始的基于样板的方法,或者使用替代方法(根据您的“检查器”代码结构的实际情况选择方式)。

答案 1 :(得分:1)

在Scala中,无法在运行时生成import语句,所有导入都在编译时解析。对于这样的用例,很容易使用包含值的Map来确定应该执行的代码(甚至代码本身以函数的形式):

// 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()