1

I'm trying to get going in Scala from the Twitter Scala School but am stumbling over syntax errors. When I run the Pattern Matching code from the "Basics continued" tutorial http://twitter.github.io/scala_school/basics2.html#match through my sbt console the compiler turns me back with "error: not found: value &&". Has something changed in Scala to take what probably worked when the tutorial was written but doesn't work now? The classes involved are

class Calculator(pBrand: String, pModel: String) {
  /**
   * A constructor
   */
  val brand: String = pBrand
  val model: String = pModel
  val color: String = if (brand.toUpperCase == "TI") {
    "blue"
  } else if (brand.toUpperCase == "HP") {
    "black"
  } else {
    "white"
  }

  // An instance method
  def add(m: Int, n: Int): Int = m + n
}

class ScientificCalculator(pBrand: String, pModel: String) extends Calculator(pBrand: String, pModel: String) {
  def log(m: Double, base: Double) = math.log(m) / math.log(base)
}

class EvenMoreScientificCalculator(pBrand: String, pModel: String) extends ScientificCalculator(pBrand: String, pModel: String) {
  def log(m: Int): Double = log(m, math.exp(1))
}

My repl looks something like this...

bobk-mbp:Scala_School bobk$ sbt console
[info] Set current project to default-b805b6 (in build file:/Users/bobk/work/_workspace/Scala_School/)
[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_17).
Type in expressions to have them evaluated.
Type :help for more information.
...
scala> def calcType(calc: Calculator) = calc match {
     |   case calc.brand == "hp" && calc.model == "20B" => "financial"
     |   case calc.brand == "hp" && calc.model == "48G" => "scientific"
     |   case calc.brand == "hp" && calc.model == "30B" => "business"
     |   case _ => "unknown"
     | }
<console>:9: error: not found: value &&
         case calc.brand == "hp" && calc.model == "20B" => "financial"
                                 ^
<console>:10: error: not found: value &&
         case calc.brand == "hp" && calc.model == "48G" => "scientific"
                                 ^
<console>:11: error: not found: value &&
         case calc.brand == "hp" && calc.model == "30B" => "business"
                                 ^
scala> 

How to I get the use case of AND on my cases when I'm doing Matching on Class Members?

Thanks in advance. I'm new to this.

Bob Kuhar
  • 10,838
  • 11
  • 62
  • 115

2 Answers2

3

If you're matching by value, as in your case, you can not only use guards, but stick to plain pattern matching:

def calcType(calc: Calculator) = (calc.brand, calc.model)  match {
     case ("hp", "20B") => "financial"
     case ("hp", "48G") => "scientific"
     case ("hp", "30B") => "business"
     case _             => "unknown"
}

I find this one easier to parse.

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
  • That's what I'm talking about! Too bad I can't undo the Right answer check as I think this version captures, exactly, the spirit of the case. What, exactly, happen here? Your function turn the brand and model values from the Calculator into a tuple and sends that kid through the match? – Bob Kuhar Jun 11 '13 at 15:09
  • Yep, what is going on here is matching against tuple. Moreover, if Calculator was a case class, you could write something like `calc match { case Calculator("hp", "20B") => "financial" .... `. *(Shameless plug -- actually you can undo)* – om-nom-nom Jun 11 '13 at 15:12
  • @BobKuhar: It is possible to undo the right answer. Just mark a different one as the right one... – kiritsuku Jun 12 '13 at 10:53
2

When you want to test a condition with a pattern, then you need to use a guard:

calc match {
  case _ if calc.brand == "hp" && calc.model == "20B" => "financial"
  ...
}

With the _ you denote that you don't bother of the concrete value calc has, but of some other condition mentioned in the guard.

Btw, it is possible to write a conjunction extractor:

object && {
  def unapply[A](a: A) = Some((a, a))
}

But it will not work in your concrete case.

Community
  • 1
  • 1
kiritsuku
  • 52,967
  • 18
  • 114
  • 136
  • Hmmm. So the twitter doc stuff can't work as written? They cover "guards", very briefly, in the section preceding the one I lifted my code from. It looks like this is a known issue: https://github.com/twitter/scala_school/pull/89 – Bob Kuhar Jun 11 '13 at 01:28
  • Thats it! But funky. The need to "capture" the _ seems redundant to me. Regardless. It compiles and my understanding of "the new shiny" has improved. – Bob Kuhar Jun 11 '13 at 01:46