Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex pattern equality

In ScalaTest, I have the following check:

"abc".r shouldBe "abc".r

But it is not equal. I don't understand.

abc was not equal to abc
ScalaTestFailureLocation: com.ing.cybrct.flink.clickstream.ConfigsTest$$anonfun$6 at (ConfigsTest.scala:97)
Expected :abc
Actual   :abc
like image 444
fluency03 Avatar asked Aug 10 '18 09:08

fluency03


People also ask

What does '$' mean in regex?

$ means "Match the end of the string" (the position after the last character in the string).

What does regex 0 * 1 * 0 * 1 * Mean?

Basically (0+1)* mathes any sequence of ones and zeroes. So, in your example (0+1)*1(0+1)* should match any sequence that has 1. It would not match 000 , but it would match 010 , 1 , 111 etc. (0+1) means 0 OR 1.

How do I match a pattern in regex?

Most characters, including all letters ( a-z and A-Z ) and digits ( 0-9 ), match itself. For example, the regex x matches substring "x" ; z matches "z" ; and 9 matches "9" . Non-alphanumeric characters without special meaning in regex also matches itself. For example, = matches "=" ; @ matches "@" .

What is \r and \n in regex?

\n. Matches a newline character. \r. Matches a carriage return character.


2 Answers

While it's possible to decide whether two regular expressions accept the same language, it seems to be rather complicated and not all that terribly useful for everyday regex usage. Therefore, equality on compiled regex patterns is just referential equality:

val x = "abc".r
val y = "abc".r
x == y
// res0: Boolean = false
like image 149
Andrey Tyukin Avatar answered Nov 02 '22 23:11

Andrey Tyukin


The method shouldBe in Scalatest 3.0.5 delegates the equality check to the areEqualComparingArraysStructurally method:

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

which in turn simply delegates the equality check (as you can expect) to the == operator:

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
      }
    }
  }
}

In Scala, at least on the JVM, == simply calls equals, which, if not overridden, checks whether the compared variables point to the same object. case classes are peculiar in that the compiler overrides equals for you to compare the constructor arguments.

You can test it very easily with the following (but as you can imagine, the same applies to simply using == on your own):

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)

  }

}

What the r method does is instantiating a new Regex object, which is not a case class and does not override the equality definition, thus yielding the result you see.

like image 41
stefanobaghino Avatar answered Nov 03 '22 00:11

stefanobaghino