在学习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
}

这是一个非常简单的过程,我会说我理解它正在尝试做的事情。我不明白的是,happysad的类型为Function1(或者至少是我的信念),但是它们可以扮演PartialFunction的角色(receive需要PartialFunction)。

甚至更糟糕的是,基于Akka documentationreceive应该返回一个PartialFunction(不是一个):

抽象def接收:Actor.Receive

Scala API:这定义了初始actor行为,它必须返回一个
具有角色逻辑的部分功能。

但据我所知,happysad没有返回PartialFunction,它们是一个。

总结我的问题:
  • 有没有办法针对PartialFunction识别Function1
  • 我读错了例子吗? receive不是返回PartialFunctionUnit吗?如果答案是肯定的,那么为什么文档说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
      }
    }
    

    更重要的是,我应该如何知道将发生哪种扩展?而且我认为现代编程语言应该更具可读性!!!

    最佳答案

    happysad的类型为Function1

    不,它们是返回 Receive 的方法,SAM typesPartialFunction[Any, Unit]的类型别名。您提供的类型注释显示了此返回类型。部分函数可以使用与Function1(和其他ojit_a)相同的lambda语法,在这种情况下,它们只能通过上下文(在这种情况下,您的类型注释)来区分。

    receive应该返回PartialFunction(不是一个)

    您对术语感到困惑。 receive是一种方法,而不是PartialFunction,正如您使用def声明的那样。它返回一个PartialFunction[Any, Unit](也称为Receive)。这也应该澄清您对happysad的困惑。

    这是造成混淆的合理原因,因为语法非常简洁,使其看起来像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。

    10-06 11:15