当我尝试在Scala中构建内部DSL时,遇到一个常见问题,而我却无法制定解决方案。为了使事情看起来更像是一种典型的语言,我希望语法看起来像这样:
model 'Foo {
decl 'Real 'x;
decl 'Real 'y;
}
实际上,有几个问题。第一个问题是在此处获取
model
对象,以这种方式接受两个参数。如果有人有任何想法,请告诉我。但是我要做的却是做一些类似的事情:model('Foo) {
...
}
现在,其中的model是一个函数,该函数然后使用
apply
方法返回对象,该方法然后使用随后的lambda。我可以忍受。我也可能在lambda内部遇到类似的问题,所以里面的像decl 'Real 'x
或decl('Real,'x)
这样的东西。但是,我想做的是获取波浪形括号内所有这些表达式的结果,以“返回”列表。换句话说,我要写的是这样的东西:model 'Foo {
decl('Real,'x);
decl('Real,'y);
}
其中
decl(...)
的计算结果为Declaration
类型,然后{...}
的计算结果为List[Declaration]
。我怀疑有某种使用隐式方法做到这一点的方法,但我一直找不到。简而言之,我想做的是:model 'Foo {
decl('Real,'x);
decl('Real,'y);
}
评估为...的等价物
model 'Foo {
decl('Real,'x) ::
decl('Real,'y) ::
Nil
}
意见或建议?
最佳答案
首先,您可以尝试使用变量参数列表,该列表允许您使用逗号而不是分号:
case class Declaration(name: String)
def decl( s: String ) = Declaration(s)
case class Model( sym: Symbol, decls: List[Declaration] )
def model( sym: Symbol)( decls: Declaration* ) =
Model( sym, decls.toList )
val m = model( 'Foo )(
decl( "bar" ),
decl( "baz" )
)
另外,您可以扩展
trait
来去除一些括号和逗号:case class ModelBuilder( sym: Symbol ) {
def using( decls: Declarations ) = Model( sym, decls.toList )
}
trait Declarations {
protected var decls = List[Declaration]()
protected def decl( s: String ) =
decls ::= Declaration( s )
def toList = decls
}
def model( sym: Symbol ) = ModelBuilder( sym )
model( 'Foo ) using new Declarations {
decl( "bar" )
decl( "baz" )
}
关于scala - 根据Scala中的一系列表达式构造一个列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10139015/