正则表达式模式相等

Regex pattern equality

在 ScalaTest 中,我进行了以下检查:

"abc".r shouldBe "abc".r

但不等于。没看懂。

abc was not equal to abc
ScalaTestFailureLocation: com.ing.cybrct.flink.clickstream.ConfigsTest$$anonfun at (ConfigsTest.scala:97)
Expected :abc
Actual   :abc

虽然它是 possible to decide whether two regular expressions accept the same language,但它似乎相当复杂,而且对于日常正则表达式的使用来说并不是那么有用。因此,编译后的正则表达式模式的相等性只是引用相等性:

val x = "abc".r
val y = "abc".r
x == y
// res0: Boolean = false

是的,它们不相等。 "abc".r 都是对两个不同内存位置的不同引用。 应该是检查equality而不是identity.

Scalatest 3.0.5 中的方法 shouldBe 将相等性检查委托给 areEqualComparingArraysStructurally 方法:

def shouldBe(right: Any): Assertion = {
  if (!areEqualComparingArraysStructurally(leftSideValue, right)) {
    val (leftee, rightee) = Suite.getObjectsForFailureMessage(leftSideValue, right)
    val localPrettifier = prettifier // Grabbing a local copy so we don't attempt to serialize AnyShouldWrapper (since first param to indicateFailure is a by-name)
    indicateFailure(FailureMessages.wasNotEqualTo(localPrettifier, leftee, rightee), None, pos)
  }
  else indicateSuccess(FailureMessages.wasEqualTo(prettifier, leftSideValue, right))
}

这又简单地将相等性检查(如您所料)委托给 == 运算符:

private[scalatest] def areEqualComparingArraysStructurally(left: Any, right: Any): Boolean = {
  // Prior to 2.0 this only called .deep if both sides were arrays. Loosened it
  // when nearing 2.0.M6 to call .deep if either left or right side is an array.
  // TODO: this is the same algo as in scalactic.DefaultEquality. Put that one in
  // a singleton and use it in both places.
  left match {
    case leftArray: Array[_] =>
      right match {
        case rightArray: Array[_] => leftArray.deep == rightArray.deep
        case _ => leftArray.deep == right
      }
    case _ => {
      right match {
        case rightArray: Array[_] => left == rightArray.deep
        case _ => left == right
      }
    }
  }
}

在 Scala 中,至少在 JVM 上,== 只是调用 equals,如果没有被重写,它会检查比较的变量是否指向同一个对象。 case classes 的特殊之处在于编译器会覆盖 equals 以便您比较构造函数参数。

您可以使用以下方法很容易地对其进行测试(但您可以想象,这同样适用于您自己简单地使用 ==):

package org.example

import org.scalatest.{FlatSpec, Matchers}

final class MyClass(val a: Int)

final case class MyCaseClass(a: Int)

final class TestSpec extends FlatSpec with Matchers {

  "equality on case classes" should "succeed" in {

    new MyCaseClass(1) shouldBe new MyCaseClass(1)

  }

  "equality on non-case classes" should "fail" in {

    new MyClass(1) shouldNot be(new MyClass(1))

  }

  "equality between Regex objects" should "fail" in {

    "abc".r shouldNot be("abc".r)

  }

}

r 方法所做的是实例化一个新的 Regex 对象,它不是 case class 并且不会覆盖相等性定义,从而产生您看到的结果。