Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: How to use case keyword without match keyword?

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!

like image 861
Guo Avatar asked Jan 05 '16 11:01

Guo


People also ask

What is case keyword in Scala?

Case classes in scala can be defined by using the case keyword. This class is a normal class like any other class in scala, but these classes are immutable, meaning we cannot change their value once assigned.

How do you write a case condition in Scala?

Using if expressions in case statements i match { case a if 0 to 9 contains a => println("0-9 range: " + a) case b if 10 to 19 contains b => println("10-19 range: " + a) case c if 20 to 29 contains c => println("20-29 range: " + a) case _ => println("Hmmm...") }

Does Scala have pattern matching?

Pattern matching is the second most widely used feature of Scala, after function values and closures. Scala provides great support for pattern matching, in processing the messages. A pattern match includes a sequence of alternatives, each starting with the keyword case.


2 Answers

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)
like image 126
Gabriele Petronella Avatar answered Oct 13 '22 00:10

Gabriele Petronella


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
like image 44
PhilBa Avatar answered Oct 12 '22 23:10

PhilBa