2009-07-27 7 views
4

私はscalaを使い慣れています。俳優を学ぶとき、私はDEFの1行を保存するためにそれを拡張しようとしました:Scalaの俳優を拡張する

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 
} 

そして、例外トレースは次のようになります。

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) 

同じことを行うことができ、多くの選択肢があるかもしれません、上記のコードがうまくいかない理由を知っている方が良いです。

答えて

8

これはかなり簡単です。この動作は実際にアクターライブラリに起因するものではありません。コード

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

の部分は、初期本体receive {...}と「Actooの新しいインスタンスを作成する」とコンパイラによって解釈取得しval actoo()に等しくなります。このように、あなたのコードは、コードを固定するために

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

にequivivalentされ、あなたはあなたが実際に(ネイティブスレッドが出演している現在のネイティブスレッド上のメールボックスから受信しようとしている

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

です。どうもありがとうございました!あなたの答えは –

1

を作成する必要があります同じように)。

証人以下:

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 

を、何を達成したいこと(Actor.actor)すでにライブラリにある:

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

ところで、拡張することは非常に悪い考えです応用。代わりにdef main(args: Array[String])を使用してください。

+0

ありがとう! アプリケーションを拡張するには何か悪いことはありますか? argsが使用されなかったときにそれらが同等であると思った... –

+0

http://scala-blogs.org/2008/07/application-trait-considered-harmful.htmlとhttp://blogs.sun.comを参照してください。/navi/en_US/entry/scala_puzzlers_part_2を参照してください。しかし、あなたが落とし穴を知っていれば、アプリケーションの特性を素早くテストするために自由に使うことができると信じています。 –

+0

Waltter、stacktraceを見ると、受信はActooオブジェクトで呼び出され、自己ではありません。しかし、Actooコンストラクターでは、アクターがまだ起動していないときに呼び出されます。 –

5

Actorには、actorという方法もあります。あなたにも自動的にstartが呼び出されます。

import scala.actors.Actor 
import Actor._ 

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

a ! 1