在Scala中构建配置DSL

在Scala中构建配置DSL,scala,configuration,code-generation,typesafe,Scala,Configuration,Code Generation,Typesafe,我想转换类型安全配置 root { mainA = "test" submodule { paramA = "value" paramB = "value" } anotherModule { zoo = 1 sub { z = test } } } 进入某种Scala配置对象,如 object config { val cfg = ConfigFactory.load() val root = "root"

我想转换类型安全配置

root {
  mainA = "test"
  submodule {
    paramA = "value"
    paramB = "value"
  }
  anotherModule {
    zoo = 1
    sub {
      z = test
    }
  }
}
进入某种Scala配置对象,如

object config {

  val cfg = ConfigFactory.load()

  val root = "root"

  lazy val mainA = cfg.getString("root.mainA")

  object submodule {
    lazy val paramA = cfg.getString("root.submodule.paramA","value")
    lazy val paramB = cfg.getString("root.submodule.paramB","value")
  }

  object anotherModule {
    lazy val zoo = cfg.getInt("root.anotherModule.zoo",1)
    object sub {
      lazy val z = cfg.getString("root.anotherModule.sub.z","test")
    }
  }
}
所以一般来说,我会有一些“模板”配置文件,并生成“通用” 具有一些默认值的配置对象

在Haskell中,我会使用模板Haskell来生成和编译代码,
在Scala中我能做些什么呢?

如果您想从Scala代码中方便地使用config,您可以尝试使用
动态
祖先来访问config。比如:

class RichConfig(cfg:Config) extends Dynamic {
  private val `intClassTag` = implicitly[ClassTag[Int]]
  def selectDynamic[T](fieldName:String)(implicit ct:ClassTag[T]) = 
    ct match {
      case `intClassTag` =>
        cfg.getInt(fieldName)
    }
}

当然,它不会让您在运行时检查是否存在配置项。

您可以使用Scala 2.10的
def
宏来实现类似类型提供程序的功能,但这有点棘手(请参阅我的博客文章以及一些示例和讨论)。一旦我们成功了,这将变得容易得多。