10
votes

I wrote a section code for testing:

class A extends JavaTokenParsers {
    def str: Parser[Any] = stringLiteral ~ ":" ~ stringLiteral ^^ 
                    { case x ~ ":" ~ y => (x, y) }    //how to use case keyword like this?
}

object B extends A with App{
    val s = """
            "name": "John"
            """
    println(parseAll(str, s))
}

I read "Chapter 15: Case Classes and Pattern Matching" of Programming in Scala Second Edition , but I never saw case used like this:

... ^^ { case x ~ ":" ~ y => (x, y) } 

It's not match keyword, but ^^ looks like match. I know partial functions and I can use case by this way:

object C extends App {
    def a(f: Int => Int) = {
        f(3)
    }
    a(x => x + 1)
    a { case x => x + 1 }
}

But they are all different:

  1. ^^ function like match, which can use content before ^^ matching content behind case
  2. case in ^^ function can use function(like ~)

How to write custom function like ^^? Can you write a concrete example? Thanks a lot!

2

2 Answers

9
votes

It's just syntactic sugar. In scala, you can use any method that takes a single parameter as a binary operator.

Example:

class Foo(x: String) {
  def ^^(pf: PartialFunction[String, Int]): Option[Int] =
    if (pf.isDefinedAt(x)) Some(pf(x)) else None
}

val foo = new Foo("bar")
foo ^^ {
  case "baz" => 41
  case "bar" => 42
}

// result: Some(42)
4
votes

As you mentioned, you can use a block with the case keyword to create a partial function.

val doubleIntGtThree: PartialFunction[Int, Int] = {
  case x: Int if x > 3 => x * 2
}
doubleIntGtThree(4) // return 8
doubleIntGtThree(2) //throws a matchError