简体   繁体   中英

Scala case syntax understanding

I'm trying to get a grip on Scala's actors (Akka), but I just came across some weird bit of "case" usage that I don't understand:

import akka.actor.{ ActorRef, ActorSystem, Props, Actor, Inbox }
import scala.concurrent.duration._

case object Greet
case class WhoToGreet(who: String)
case class Greeting(message: String)

class Greeter extends Actor {

    var greeting = ""

    def receive = {
        case WhoToGreet(who) => greeting = s"hello, $who"
        case Greet           => sender ! Greeting(greeting) // Send the current greeting back to the sender
    }

}

This bit in particular:

  def receive = {
      case WhoToGreet(who) => greeting = s"hello, $who"
      case Greet           => sender ! Greeting(greeting) // Send the current greeting back to the sender
  }

Now I thought that case syntax in scala looks like this:

something match {
    case "val1" => println("value 1")
    case "val2" => println("value 2")
}

If I try to replicate the usage in question in scala REPL like this:

def something = {
    case "val1" => println("value 1")
    case "val2" => println("value 2")
}

I get

error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)

What exactly does this mean?

UPDATE: This article is by far the best answer to my question: http://blog.bruchez.name/2011/10/scala-partial-functions-without-phd.html

Case Syntax in scala has a number of forms it can take.

Some examples are:

case personToGreet: WhoToGreet => println(personToGreet.who)
case WhoToGreet(who) => println(who)
case WhoToGreet => println("Got to greet someone, not sure who")
case "Bob" => println("Got bob")
case _ => println("Missed all the other cases, catchall hit")

The reason you're seeing that error is because you didn't attempt to invoke match on a known object, but instead tried to assign a case block to a function.

Because a Case block is just a PartialFunction deep down, the compiler thinks you're trying to define a partial function but not giving it enough info because there's nothing for it to apply to.

Try something like:

def something: PartialFunction[Any,Unit] = {
    case "val1" => println('value 1")
    case _ => println("other")
}

And you'll be able to invoke it.

Edit

The case in the Akka example works because you're actually providing an implementation for an abstract, pre-existing function: receive is defined in akka.actor.Actor. You can see the typedef in the Akka source :

object Actor {
  type Receive = PartialFunction[Any, Unit]
  ..
}

trait Actor {
  def receive: Actor.Receive 
  ....
} 

The receive call in the example is compiled to

def receive: PartialFunction[Any, Unit] = {
}

Which tells us that Receive will take any value or reference and return a unit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM