Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 是什么导致以下运算符重载交换操作数?_Scala_Operator Overloading_Scala Compiler - Fatal编程技术网

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

我用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: 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
将无法工作。实际上,我很惊讶您以前从未遇到过这种语法。