2

简而言之:我尝试为A <N BScala 中的 DSL 编写类似 T 类型的整数 N 和 A,B 的东西。这样做有很好的可能性吗?

Longer:我尝试在 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!
4

2 回答 2

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
于 2013-04-02T08:24:34.610 回答
0

问题是apply它不能作为后缀运算符工作,所以没有括号你不能写它,你可以这样写:

  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"))

如果不在某处添加括号,就没有做你想做的事的好方法。

我认为如果您真的想坚持使用这种语法,您可能想要使用组合解析器。或者正如@korefn 建议的那样,您破坏了兼容性并使用新的运算符来实现。

于 2013-04-02T14:36:05.927 回答