Scala 是什么导致以下运算符重载交换操作数?
我用scala语言定义了两个操作符:Scala 是什么导致以下运算符重载交换操作数?,scala,operator-overloading,scala-compiler,Scala,Operator Overloading,Scala Compiler,我用scala语言定义了两个操作符::++和++:,它们是彼此的精确镜像:a:+++b==b++:a,它们显然是不可交换的:a:+++b!=a++:b 这是我的scala测试代码: import org.scalatest.FunSpec import scala.collection.immutable.ListMap case class Example(self: ListMap[String, String] = ListMap.empty) { def :++(v: Exam
:++
和++:
,它们是彼此的精确镜像:a:+++b==b++:a
,它们显然是不可交换的:a:+++b!=a++:b
这是我的scala测试代码:
import org.scalatest.FunSpec
import scala.collection.immutable.ListMap
case class Example(self: ListMap[String, String] = ListMap.empty) {
def :++(v: Example) = this.copy(
self ++ (v.self -- self.keys.toSeq)
)
def ++:(v: Example) = {
println("forward: " + :++(v))
println("reverse: " + (v :++ this))
v :++ this
}
}
class OperatorOverrideSuite extends FunSpec {
val p1 = Example(ListMap("a" -> "1"))
val p2 = Example(ListMap("a" -> "2"))
it(":++ operator should preserve first value") {
assert(p1 :++ p2 == p1)
}
it("++: operator should preserve second value") {
assert(p1 ++: p2 == p2)
}
}
第一个测试看起来很好,但在运行时,我遇到了以下错误:
forward: Example(Map(a -> 2))
reverse: Example(Map(a -> 1))
Example(Map(a -> 1)) did not equal Example(Map(a -> 2))
ScalaTestFailureLocation: com.schedule1.datapassports.params.OperatorOverrideSuite$$anonfun$2 at (OperatorOverrideSuite.scala:30)
Expected :Example(Map(a -> 2))
Actual :Example(Map(a -> 1))
<Click to see difference>
org.scalatest.exceptions.TestFailedException: Example(Map(a -> 1)) did not equal Example(Map(a -> 2))
at org.scalatest.Assertions$class.newAssertionFailedException(Assertions.scala:528)
at org.scalatest.FunSpec.newAssertionFailedException(FunSpec.scala:1630)
at org.scalatest.Assertions$AssertionsHelper.macroAssert(Assertions.scala:501)
at ...
转发:示例(映射(a->2))
反向:示例(映射(a->1))
示例(图(a->1))不等于示例(图(a->2))
ScalaTestFailureLocation:com.schedule1.datapassports.params.OperatorOverrideSuite$$anonfun$2 at(OperatorOverrideSuite.scala:30)
预期:示例(映射(a->2))
实际:示例(地图(a->1))
org.scalatest.exceptions.TestFailedException:示例(映射(a->1))不等于示例(映射(a->2))
位于org.scalatest.Assertions$class.newAssertionFailedException(Assertions.scala:528)
位于org.scalatest.FunSpec.newAssertionFailedException(FunSpec.scala:1630)
位于org.scalatest.Assertions$assertionHelper.macroserte(Assertions.scala:501)
在
从打印出来的消息来看,scala似乎重写了my运算符并自己反转操作数,是什么导致scala编译器以这种方式运行?是虫子吗
我正在使用最新的scala 2.11和最新的Java 8u181进行测试。来自scala语言:
运算符的关联性由该运算符的最后一个
性格以冒号“:”结尾的运算符是右关联的。全部的
其他操作符是左关联的
下面是一个例子:
scala> case class Test(name: String) {
| def ++:(that: Test) = println(s"Called ++: on $this with argument $that")
| def :++(that: Test) = println(s"Called :++ on $this with argument $that")
| }
defined class Test
scala> val (x, y) = (Test("x"), Test("y"))
x: Test = Test(x)
y: Test = Test(y)
scala> x ++: y
Called ++: on Test(y) with argument Test(x)
scala> x :++ y
Called :++ on Test(x) with argument Test(y)
因此,当您在代码中说p1++:p2
时,执行的是p2.++:(p1)
,这相当于p1:+++p2
。这意味着您的两个运算符实际上是严格等价的。来自Scala语言:
运算符的关联性由该运算符的最后一个
性格以冒号“:”结尾的运算符是右关联的。全部的
其他操作符是左关联的
下面是一个例子:
scala> case class Test(name: String) {
| def ++:(that: Test) = println(s"Called ++: on $this with argument $that")
| def :++(that: Test) = println(s"Called :++ on $this with argument $that")
| }
defined class Test
scala> val (x, y) = (Test("x"), Test("y"))
x: Test = Test(x)
y: Test = Test(y)
scala> x ++: y
Called ++: on Test(y) with argument Test(x)
scala> x :++ y
Called :++ on Test(x) with argument Test(y)
因此,当您在代码中说
p1++:p2
时,执行的是p2.++:(p1)
,这相当于p1:+++p2
。这意味着您的两个操作员实际上是严格等效的。哇,我以前从未见过这个规则,它是SIP的一个吗?如果操作符是:+:,会发生什么?我试图在某个文档中找到它,但到目前为止找不到。我想我是在不久前从奥德斯基那里读到Scala编程时学会的。@tribbloid:这和Scala本身一样古老,远远早于SIP进程。如果没有正确的关联运算符,Scala中最重要的语法之一,someElement::someList
将无法工作。我真的很惊讶你以前从未遇到过这种语法。哇,我以前从未见过这个规则,它是SIP的一个吗?如果操作符是:+:,会发生什么?我试图在某个文档中找到它,但到目前为止找不到。我想我是在不久前从奥德斯基那里读到Scala编程时学会的。@tribbloid:这和Scala本身一样古老,远远早于SIP进程。如果没有正确的关联运算符,Scala中最重要的语法之一,someElement::someList
将无法工作。实际上,我很惊讶您以前从未遇到过这种语法。