简而言之:我尝试为Scala中的DSL编写类似A <N B
的内容,输入类型T的整数N和A,B。这样做很有可能?
更长:我尝试在Scala中为TGrep2编写DSL。我现在有兴趣写
A <N B B is the Nth child of A (the rst child is <1).
以一种很好的方式,尽可能接近Scala中的原始定义。有没有办法重载<
运算符,它可以将N和B作为参数。
我尝试了什么:我尝试了两种不同的可能性并没有让我感到高兴:
scala> val N = 10
N: Int = 10
scala> case class T(n:String) {def <(i:Int,j:T) = println("huray!")}
defined class T
scala> T("foo").<(N,T("bar"))
huray!
和
scala> case class T(n:String) {def <(i:Int) = new {def apply(j:T) = println("huray!")}}
defined class T
scala> (T("foo")<N)(T("bar"))
warning: there were 1 feature warnings; re-run with -feature for details
huray!
答案 0 :(得分:3)
我建议您使用类似nth
的内容而不是<
符号,以使语义清晰。 A nth N is B
至少对我很有意义。它会转化为类似
case class T (label:String){
def is(j:T) = {
label equals j.label
}
}
case class J(i:List[T]){
def nth(index:Int) :T = {
i(index)
}
}
您可以轻松完成:
val t = T("Mice")
val t1 = T("Rats")
val j = J(List(t1,t))
j nth 1 is t //res = true
答案 1 :(得分:0)
问题是apply
不能用作后缀运算符,所以你不能在没有parantheses的情况下编写它,你可以这样写:
case class T(n: String) {
def <(in: (Int, T)) = {
in match {
case (i, t) =>
println(s"${t.n} is the ${i} child of ${n}")
}
}
}
implicit class Param(lower: Int) {
def apply(t: T) = (lower, t)
}
然后,
T("foo") < 10 T("bar")
仍然会失败,但您可以通过以下方式解决问题:
T("foo") < 10 (T("bar"))
如果不在某处添加括号,就没有办法做你想做的事。
如果您真的想坚持使用这种语法,我认为您可能想要使用combinational parser。或者正如@korefn所提议的那样,你会破坏兼容性并与新的运算符一起使用。