Scala运算符使用多个参数进行重载

时间:2013-04-02 07:46:14

标签: scala syntax operator-overloading dsl

简而言之:我尝试为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!

2 个答案:

答案 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所提议的那样,你会破坏兼容性并与新的运算符一起使用。

相关问题