1

在一些教程的指导下,我一直在尝试获得一个简单的 Scala Actor 示例,在该示例中,我向演员发送(字符串)消息,并且该演员回复控制台的输出。我的代码是:

import scala.io.Source
import scala.actors.Actor

object ProtTest {

  class testActor extends Actor {
    def receive = { 
      case "you" => Console.println("Hello you!")
      case _ => Console.println ("Hello ???")
    }
  }

  val t = new testActor
  t ! "you"
}

不幸的是,我在“def receive = {”上收到以下错误消息,并且已经停留了很长一段时间:

Missing parameter type for expanded function 
The argument types of an anonymous function must be fully known (SLS 8.5)
Expected Type was: ?

我真的不知道错误消息中的问号是什么意思以及如何修复示例以便它可以工作?!

4

3 回答 3

5

看起来你对演员的实现有点困惑。您的testActor代码对Akka演员有效,但您使用的是 Scala 演员库。

Akka 和 scala.actors 是 Actor 模型的两个不同实现。Scala actor 是最初的实现,但 Akka 现在更流行(并且在 IMO 上更出色),并且从 Scala 2.10 开始,它是与 Scala 捆绑在一起的标准实现(scala.actors 存在,但在 2.10 中已弃用)。

我实际上不知道如何正确实现一个 scala 演员,但这里是如何让你的演员在 Akka 中运行:

import akka.actor._

object ProtTest {

  class testActor extends Actor {
    def receive = { 
      case "you" => Console.println("Hello you!")
      case _ => Console.println ("Hello ???")
    }

    override def postStop() {
      context.system.shutdown
    }
  }

  val system = ActorSystem("test")
  val t = system.actorOf(Props[testActor])
  t ! "you"
  t ! PoisonPill
  system.awaitTermination

}

如您所见,Akka 需要一些样板来正确设置和关闭 Actor 系统,但您的主要 Actor 代码没有改变。该postStop方法在actor关闭后调用,这发生在actor接收到PoisonPill消息时。

于 2013-01-22T16:15:57.270 回答
3

receive不是您实施的方法。您需要act调用 receive时执行:

  class testActor extends Actor {
    def act = {
      while (true) {
        receive {
          case "you" => Console.println("Hello you!")
          case _ => Console.println ("Hello ???")
        }
      }
    }
  }

receive您调用的方法也是如此。您传递给它的参数是{..}包含 case 子句的代码块。这个参数的类型是一个部分函数- 在你的例子中,一个函数从String(scala推断,因为“你”是一个字符串)到Unit(scala的版本voidprintln返回的)。

(有关偏函数如何等效于一堆case语句的详细说明,请参阅 Twitters 的 Scala School)。

一旦你了解了基本的 scala 概念,编译错误消息就很容易理解了——在这种情况下,知道匿名函数和_速记的行为可能是必要的。

t.start此外,如果您希望它接收消息,您需要启动您的参与者实例。

虽然尚未弃用,但大多数人(正如另一个答案指出的那样)偏爱 Akka 演员。 从 Scala 2.10 开始,scala.actors.Actor不推荐使用 Akka actor。

(作为旁注,如果您希望该代码工作,您还需要声明ProtTest为扩展App或将调用移动t ! "you"到具有 main 方法的类(或对象))

于 2013-01-22T15:20:15.580 回答
0

我使用 Akka 比使用 Scala 的 actor 系统更多,但是……这里有一个简短的教程;您可以从那里的示例中看到,该receive块应该在一个循环(例如while (true) {...})内,在一个def act()方法内。

于 2013-01-22T15:20:16.240 回答