Scala case语法理解

3

我正在尝试掌握Scala的actors(Akka),但我刚刚遇到了一些奇怪的“case”用法,我不理解:

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
    }

}

这部分内容:

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

现在我认为Scala中的案例语法如下:
something match {
    case "val1" => println("value 1")
    case "val2" => println("value 2")
}

如果我想在Scala REPL中复制这个问题的用法,就像这样:
def something = {
    case "val1" => println("value 1")
    case "val2" => println("value 2")
}

我明白了

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

这是什么意思呢?

更新: 这篇文章目前是回答我问题的最佳答案:http://blog.bruchez.name/2011/10/scala-partial-functions-without-phd.html

1个回答

3

Scala中的Case语法有多种形式。

一些例子包括:

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")

您看到该错误的原因是因为您没有尝试在已知对象上调用match,而是尝试将case块分配给函数。
因为Case块本质上只是一个PartialFunction,所以编译器认为您正在尝试定义一个部分函数,但没有足够的信息让它应用于任何内容。
请尝试类似以下的操作:
def something: PartialFunction[Any,Unit] = {
    case "val1" => println('value 1")
    case _ => println("other")
}

您将能够调用它。

编辑

Akka示例中的情况是可行的,因为您实际上正在为预先存在的抽象函数提供实现:receive在akka.actor.Actor中定义。您可以在Akka源代码中看到typedef:

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

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

在这个例子中,receive调用被编译为:

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

这告诉我们,Receive将接受任何值或引用,并返回一个单位。

我知道使用match可以解决问题,但我的问题仍然存在 - 为什么在Akka示例中不使用match也能工作?我在网上找不到任何关于这种语法的参考资料。 - Caballero
抱歉,我完全忽略了您需要澄清那一点。已经在答案中编辑好了 :) - Damiya
1
@Caballero,它能够与receive一起工作的原因是您正在覆盖它并且父类型Actor定义了函数的类型,这是一个PartialFunction...。要定义自己的部分函数,您只需要定义正确的返回类型(PartialFunction)。有关示例,请参见文档:http://www.scala-lang.org/api/2.10.3/index.html#scala.PartialFunction - yǝsʞǝla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接