在学习Scala和Akka的过程中,我试图了解人们如何发现一个PartialFunction。
在“编程反应系统”课程中,有一个Actor的示例:
class Toggle extends Actor {
def happy: Receive = {
case "How are you?" =>
sender ! "happy"
context become sad
}
def sad: Receive = {
case "How are you?" =>
sender ! "sad"
context become happy
}
def receive = happy
}
Run Code Online (Sandbox Code Playgroud)
这是一个非常简单的过程,我会说我理解它正在尝试做的事情。我不明白的事情是,happy和sad有型的Function1(或至少这是我的信念),但他们能发挥的作用的PartialFunction(receive需要PartialFunction)。
而且甚至更糟糕的是,根据Akka文档,receive应该返回一个PartialFunction(不是一个):
抽象def接收:Actor.Receive
Scala API:这定义了初始actor行为,它必须返回具有actor逻辑的部分函数。
但是据我所知,happy并且sad不返回a PartialFunction,它们是一个。
总结我的问题:
PartialFunction反对Function1?receive一个PartialFunction是回报Unit?如果答案是肯定的,那么为什么文档说receive应该返回PartialFunction??[更新]
根据我从@Brian McCutchon得到的答案,现在我知道该receive方法应该返回PartialFunction。但这根本无法解决我的困惑!请考虑以下情形:
def someFunction(): Receive = {
//Instantiates and returns a Receive object
}
class Toggle {
def happy: Receive = {
case "How are you?" =>
someFunction()
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,Scala编译器如何知道给定的代码是否应该扩展为:
class Toggle {
def happy: Receive = {
return {
case "How are you?" =>
someFunction() // <-- The returned object of this function call is dismissed
}
}
}
Run Code Online (Sandbox Code Playgroud)
或这个:
class Toggle {
def happy: Receive = { // <-- Starting point of happy's body
case "How are you?" =>
someFunction() // <-- The Receive object is returned by this method
}
}
Run Code Online (Sandbox Code Playgroud)
更重要的是,我应该如何知道将发生哪种扩展?而且我认为现代编程语言应该更具可读性!!!
happy并且sad属于Function1类型
不,它们是return的方法Receive,这是的类型别名PartialFunction[Any, Unit]。您提供的类型注释显示了此返回类型。部分函数可以使用与Function1(和其他SAM类型)相同的lambda语法,在这种情况下,它们只能通过上下文(在这种情况下,您的类型注释)来区分。
receive应该返回一个PartialFunction(不是一个)
您对术语感到困惑。receive是方法,而不是PartialFunction您用声明的方法def。它返回一个PartialFunction[Any, Unit](aka Receive)。这也应该澄清您对happy和的困惑sad。
这是混乱的合理来源,因为语法是如此简洁,以使它看起来像receive和PartialFunction它的回报是一回事。这可能有助于认识到您的代码可以扩展为此(尽管我在实践中不建议这样做):
class Toggle extends Actor {
def happy: Receive = {
return {
case "How are you?" =>
sender ! "happy"
context become sad
}
}
def sad: Receive = {
return {
case "How are you?" =>
sender ! "sad"
context become happy
}
}
def receive = {
return happy
}
}
Run Code Online (Sandbox Code Playgroud)
根据您的更新,第一个扩展是正确的。第二个没有意义,因为方法主体不能以开头case,这应该提示您正在处理lambda。总结一下:如果一个块以lambda参数开头(例如x =>),或者它以case而不是match块开头,则为lambda。