2

Everything started from a couple of considerations:

  • Extractors are Scala objects that implements some unapply methods with certain peculiarities (directly from «Programming in Scala 2nd edition», I've checked)
  • Objects are singletons lazy initialised on the static scope

I've tried to implement a sort of «parametric extractors» under the form of case classes to try to have an elegant pattern for SHA1 checking.

I'd like to check a list of SHA1s against a buffer to match which of them apply. I'd like to write something like this:

val sha1: Array[Byte] = ...
val sha2: Array[Byte] = ...

buffer match {
  case SHA1(sha1) => ...
  case SHA1(sha2) => ...
  ...
}

Ok, it looks weird, but don't bother now.

I've tried to solve the problem by simply implementing a case class like this

case class SHA1(sha1: Array[Byte]) {
  def unapply(buffer: Array[Byte]): Boolean = ...
}

and use it like

case SHA1(sha1)() =>

and even

case (SHA1(sha1)) =>

but it doesn't work: compiler fails.

Then I've a little changed the code in:

val sha1 = SHA1(sha1)
val sha2 = SHA1(sha2)
buffer match {
  case sha1() => println("sha1 Match")
  case sha2() => println("sha2 Match")
  ...
}

and it works without any issue.

Questions are:

Q1: There are any subtle implications in using such a kind of «extractors»

Q2: Provided the last example works, which syntax was I supposed to use to avoid to define temporary vals? (if any provided compiler's job with match…case expressions)


EDIT The solution proposed by Aaron doesn't work either. A snippet:

case class SHA1(sha1: Array[Byte]) { 
  def unapply(buffer: Array[Byte]) = buffer.length % 2 == 0
}

object Sha1Sample {
  def main(args: Array[String]) {
    println("Sha1 Sample")

    val b1: Array[Byte] = Array(0, 1, 2)
    val b2: Array[Byte] = Array(0, 1, 2, 3)
    val sha1 = SHA1(b1)
    List(b1, b2) map { b =>
      b match {
        case sha1() => println("Match") // works
        case `sha1` => println("Match") // compile but it is semantically incorrect
        case SHA1(`b1`) => println("SOLVED")  // won't compile
        case _ => println("Doesn't Match")
      }
    }
  }
}
Lord of the Goo
  • 1,214
  • 15
  • 31

1 Answers1

0

Short answer: you need to put backticks around lowercase identifiers if you don't want them to be interpreted as pattern variables.

case Sha1(`sha1`) => // ...

See this question.

Community
  • 1
  • 1
Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
  • It seems it doesn't work either. Please review my edited post. Thank you. – Lord of the Goo Nov 21 '13 at 09:44
  • Ah, I see. I misunderstood your use case. The compiler is expecting a pattern extractor where your `SHA1` appears, so yes you'll need to apply `SHA1` to a specific hash outside of the match expression. – Aaron Novstrup Nov 21 '13 at 21:30