2013-07-25 13 views
6

私はScala 2.10先物を使用して非同期ライブラリを作成しています。ライブラリのコンストラクタは、特定の特性を実装する一連のユーザー定義オブジェクトを受け取り、ライブラリクラスのメソッドは、ユーザー定義オブジェクトにデータを1つずつ送信します。メインインスタンスを設定するときに非同期操作のためにExecutionContextを提供し、そのコンテキストが必要に応じてユーザー定義オブジェクトに渡されるようにします。簡素化された(?擬似)コード:含めるオブジェクト/呼び出されたメソッドに暗黙のExecutionContextを渡す

case class Response(thing: String) 

class LibraryObject(stack: Seq[Processor])(implicit context: ExecutionContext) { 
    def entryPoint(data: String): Future[Response] = { 
    val response = Future(Response("")) 
    stack.foldLeft(response) { (resp, proc) => proc.process(data, resp) } 
    } 
} 

trait Processor { 
    def process(data: String, resp: Future[Response]): Future[Response] 
} 

それはこのようなものを使用することがあります

class ThingProcessor extends Processor { 
    override def process(data: String, response: Future[Response]) = { 
    response map { _.copy(thing = "THE THING") } 
    } 
} 

class PassThroughProcessor extends Processor { 
    override def process(request: Request, response: Future[Response]) = { 
    response 
    } 
} 

object TheApp extends App { 
    import ExecutionContext.Implicits.global 

    val stack = List(
    new ThingProcessor, 
    new PassThroughProcessor 
) 
    val libObj = new LibraryObject(stack) 

    val futureResponse = libObj.entryPoint("http://some/url") 

    // ... 
} 

私はThingProcessorのためにコンパイルエラーを取得:

暗黙的のExecutionContextを見つけることができませんあなた自身または輸入者のどちらかが必要ですExecutionContext.Implicits.global

私はExecutionContextLibraryObjectがユーザー定義オブジェクト(ThingProcessorPassThroughProcessor)またはそのメソッドに暗黙的に(クラスを作成する)ユーザーに気にせずに提供することはできますか?

class MyFirstProcessor(implicit context: ExecutionContext) 

または

override def process(...)(implicit context: ExecutionContext) = { ... } 

答えて

5

を暗黙的スコープは、コンパニオンオブジェクトと基本の型パラメータが含まれていますと言って、私は、ユーザーががないを入力する必要がなかったことを好むだろうクラス。

または、library.submit(新しいライブラリ.Processor {def process()...})。

これは動作しますが、より巧妙であることだった私の最初の考えはなかった。

import concurrent._ 
import concurrent.duration._ 

class Library(implicit xc: ExecutionContext = ExecutionContext.global) { 
    trait Processor { 
    implicit val myxc: ExecutionContext = xc 
    def process(i: Future[Int]): Future[Int] 
    } 

    def submit(p: Processor) = p process future(7) 
} 

object Test extends App { 
    val library = new Library 
    val p = new library.Processor { 
    def process(i: Future[Int]) = for (x <- i) yield 2 * x 
    } 
    val res = library submit p 
    val z = Await result (res, 10.seconds) 
    Console println z 
} 

更新:それはストレッチのあまりないです

import concurrent._ 
import concurrent.duration._ 
import java.util.concurrent.Executors 

class Library()(implicit xc: ExecutionContext = ExecutionContext.global) { 
    trait Processor { 
    implicit val myxc: ExecutionContext = xc 
    def process(i: Future[Int]): Future[Int] 
    } 

    def submit(p: Processor) = p process future(7) 
} 

object ctx { 
    val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor 
} 
object library1 extends Library 
object library2 extends Library()(ctx.xc) 
object p extends library1.Processor { 
    def process(i: Future[Int]) = for (x <- i) yield 2 * x 
} 
object q extends library2.Processor { 
    def process(i: Future[Int]) = for (x <- i) yield 3 * x 
} 

object Test extends App { 
    val res = library1 submit p 
    //val oops = library2 submit p 
    //val oops = library1 submit q 
    val z = Await result (res, 10.seconds) 
    Console println z 
    Console println (Await result (library2 submit q, 10.seconds)) 
    ctx.xc.shutdownNow() 
} 

class Library(implicit xc: ExecutionContext = ExecutionContext.global) { 

    def submit(p: Processor): Future[Int] = p dueProcess future(7) 
} 
trait Processor { 
    implicit var myxc: ExecutionContext = _ 
    def dueProcess(i: Future[Int])(implicit xc: ExecutionContext) = { 
    myxc = xc 
    process(i) 
    } 
    protected def process(i: Future[Int]): Future[Int] 
} 

object ctx { 
    val xc = ExecutionContext fromExecutorService Executors.newSingleThreadExecutor 
} 
object Test extends App { 
    def db() = Console println (new Throwable().getStackTrace mkString ("TRACE [\n ", "\n ", "\n]")) 
    val library = new Library()(ctx.xc) 
    val p = new Processor { 
    protected def process(i: Future[Int]) = for (x <- i) yield { db(); 2 * x } 
    } 
    val res = library submit p 
    val z = Await result (res, 10.seconds) 
    Console println z 
    ctx.xc.shutdownNow() 
} 
+1

これはシングルトンオブジェクトではありませんが、明らかに回避策はありますか? –

+0

@ pagoda_5bあなたはアップデートのような意味ですか?私がはっきりと考えていないならば、事前に謝罪してください。 –

+0

うん、かなり滑らかに見えて、私はそれが好きです。 –