在学习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
}
这是一个非常简单的过程,我会说我理解它正在尝试做的事情。我不明白的是,
happy
和sad
的类型为Function1
(或者至少是我的信念),但是它们可以扮演PartialFunction
的角色(receive
需要PartialFunction)。甚至更糟糕的是,基于Akka documentation,
receive
应该返回一个PartialFunction
(不是一个):抽象def接收:Actor.Receive
Scala API:这定义了初始actor行为,它必须返回一个
具有角色逻辑的部分功能。
但据我所知,
happy
和sad
没有返回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()
}
}
我的问题是,Scala编译器如何知道给定的代码是否应该扩展为:
class Toggle {
def happy: Receive = {
return {
case "How are you?" =>
someFunction() // <-- The returned object of this function call is dismissed
}
}
}
或这个:
class Toggle {
def happy: Receive = { // <-- Starting point of happy's body
case "How are you?" =>
someFunction() // <-- The Receive object is returned by this method
}
}
更重要的是,我应该如何知道将发生哪种扩展?而且我认为现代编程语言应该更具可读性!!!
最佳答案
happy
和sad
的类型为Function1
不,它们是返回 Receive
的方法,SAM types是PartialFunction[Any, Unit]
的类型别名。您提供的类型注释显示了此返回类型。部分函数可以使用与Function1
(和其他ojit_a)相同的lambda语法,在这种情况下,它们只能通过上下文(在这种情况下,您的类型注释)来区分。
receive
应该返回PartialFunction
(不是一个)
您对术语感到困惑。 receive
是一种方法,而不是PartialFunction
,正如您使用def
声明的那样。它返回一个PartialFunction[Any, Unit]
(也称为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
}
}
根据您的更新,第一个扩展是正确的。第二个没有意义,因为方法主体不能以
case
开头,这应该提示您正在处理lambda。总结一下:如果一个块以lambda参数开头(例如x =>
),或者它以case
开头并且不是match
块,则为lambda。