2009-07-27 7 views
4

Ich bin neu in Scala. Als Schauspieler lernen, habe ich versucht, sie zu verlängern eine Zeile def zu speichern:Extending Scala Actor

import scala.actors.Actor 
import Actor._ 
class Actoo(actoo: =>Unit) extends Actor { 
    def act() {actoo} 
} 
object run extends Application { 
    /* 
    // this one runs well 
    val a = new Actor { 
     def act() { 
      receive { case 1 => println("1") } 
     } 
    } 
    */ 
    val a = new Actoo { 
     receive { case 1 => println("1") } 
    } 
    a.start 
    a ! 1 
} 

Dann wird die Ausnahme-Trace sieht wie folgt aus:

java.lang.AssertionError: assertion failed: receive from channel belonging to other actor 
    at scala.Predef$.assert(Predef.scala:92) 
    at scala.actors.Actor$class.receive(Actor.scala:424) 
    at Actoo.receive(actoo.scala:3) 
    at run$$anon$1.<init>(actoo.scala:16) 
    at run$.<init>(actoo.scala:15) 
    at run$.<clinit>(actoo.scala) 
    at run.main(actoo.scala) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at scala.tools.nsc.ObjectRunner$$anonfun$run$1.apply(ObjectRunner.scala:75) 
    at scala.tools.nsc.ObjectRunner$.withContextClassLoader(ObjectRunner.scala:49) 
    at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:74) 
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:154) 
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 

Es gibt viele Alternativen sein können, die das gleiche tun kann, aber es ist besser für mich zu wissen, warum der obige Code nicht funktioniert.

Antwort

8

Es ist ziemlich einfach. Dieses Verhalten ist nicht auf die Bibliothek von Schauspielern zurückzuführen. Das Stück Code

val a = new Actoo { 
     receive { case 1 => println("1") } 
    } 

von einem Compiler als „erstellen neue Instanz von Actoo“ mit einem Initialisierungsschritt Körper interpretiert wird und receive {...}val actoo gleich (). Somit wird Ihr Code equivivalent zu

val a = new Actoo() { 
     receive { case 1 => println("1") } 
    } 

Um den Code zu beheben, müssen Sie

val a = new Actoo ({ 
     receive { case 1 => println("1") } 
    }) 
+0

es funktioniert! vielen Dank! –

1

Sie tatsächlich versuchen, schreiben, aus Postfach auf dem aktuellen native Thread (native Threads sind Schauspieler zu erhalten auch).

Zeuge folgendes:

Welcome to Scala version 2.7.5.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_13). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> import scala.actors.Actor._ 
import scala.actors.Actor._ 

scala> self ! 123 

scala> receive { case x => println(x) } 
123 

Nun, was wollen Sie ist in der Bibliothek erreichen bereits (Actor.actor):

val a = actor { 
    receive { case x => println(x) } 
} 
// no need to start a 
a ! 123 

BTW, ist es eine sehr schlechte Idee zu verlängern Anwendung. Verwenden Sie stattdessen def main(args: Array[String]).

+0

danke für deine antwort! Gibt es etwas Schlechtes, um die Anwendung zu erweitern? Ich dachte, sie waren gleichwertig, wenn Args nicht verwendet wurden ... –

+0

Bitte siehe http://scala-blogs.org/2008/07/application-trait-considered-harmful.html und http://blogs.sun.com/navi/de_DE/entry/scala_puzzlers_part_2 für eine gute Erklärung der Fallstricke bei der Verwendung der Application-Eigenschaft. Allerdings glaube ich, wenn Sie die Fallstricke kennen, können Sie absolut frei, Anwendung Merkmal für schnelle Testzwecke –

+0

Walter verwenden, wenn Sie auf den StackTrace schauen, werden Sie sehen, der Empfang wird Actoo Objekt, nicht Selbst aufgerufen. Aber der Aufruf findet im Actoo-Konstruktor statt, wenn der Actor noch nicht gestartet ist. –

5

Es gibt auch eine actor Methode in der Actor Singleton, die das tut, was Sie wollen. Es ruft sogar automatisch start für Sie an.

import scala.actors.Actor 
import Actor._ 

val a = actor { 
    receive { case 1 => println("1") } 
} 

a ! 1