18

演習として、関数を受け入れて を生成する暗黙的な変換を作成しようとしましたRunnable。そうすれば、Runnableオブジェクトを受け入れる Java メソッドを呼び出して、それらをクロージャのように使用できます。

暗黙の変換は簡単です:

    implicit def funToRunnable(fun : Unit) = new Runnable() { def run = fun }

しかし、私はそれを呼び出す方法がわかりません。一度に評価することなく、Unit を返す引数なしの関数をどのように渡しますか? たとえば、次のように「12」を出力したいのですprint("2")が、一度に評価されるため、代わりに「21」を出力します。

    var savedFun : Runnable = null
    def save(r : Runnable) = { savedFun = r }

    save(print("2"))
    print("1")
    savedFun.run()

print("2")一度に評価されるものではなく、関数の本体として扱うようにコンパイラに指示するにはどうすればよいですか? 私が試したいくつかの可能性、

    save(() => print("2"))

また

    save(=> print("2"))

は正当な構文ではありません。

4

5 に答える 5

24

arg、ちょうど私自身の質問に答えました。暗黙の変換を間違って実装しました。正しい実装は

implicit def funToRunnable(fun: () => Unit) = new Runnable() { def run() = fun() }

そして、あなたはそれを次のように呼びます:

save(() => print("2"))

これにより、「2」が得られます

于 2010-06-18T23:40:25.723 に答える
14

危険な生活を送りたい場合は、何でも実行可能に変換できます。

implicit def whateverToRunnable[F](f: => F) = new Runnable() { def run() { f } }

scala> val t = new Thread(println("Hello"))
t: java.lang.Thread = Thread[Thread-2,5,main]

scala> t.start()
Hello

または、独自のスレッド作成者とスターターを作成することもできます。

def thread[F](f: => F) = (new Thread( new Runnable() { def run() { f } } )).start

scala> thread { println("Hi"); Thread.sleep(1000); println("Still here!") }
Hi

scala> Still here!

スレッドを返したい場合は、

def thread[F](f: => F) = {
  val t = new Thread( new Runnable() { def run() { f } } )
  t.start()
  t
}

scala.actors.Futuresしかし、これはすべて有用ですが、おそらく(2.8でのみテストされた)よりもさらに有用ではありません。

scala> import scala.actors.Futures

scala> val x = Futures.future { Thread.sleep(10000); "Done!" }
x: scala.actors.Future[java.lang.String] = <function0>

scala> x.isSet
res0: Boolean = false

scala> x.isSet
res1: Boolean = false

scala> x()   // Waits until the result is ready....
res2: java.lang.String = Done!
于 2010-06-19T02:09:49.397 に答える
5

Runnable興味深いことに、この方法で を受け取ってクロージャを渡すコードを実行できます。

見る:

scala> new Thread( ()  => print( "Hello" ) ).start()
<console>:5: error: overloaded method constructor Thread with alternatives (java.lang.ThreadGroup,java.lang.Runnable,java.lang.String,Long)java.lang.Thread <and> (java.lang.ThreadGroup,java.lang.Runnable,java.lang.String)java.lang.Thread <and> (java.lang.Runnable,java.lang.String)java.lang.Thread <and> (java.lang.ThreadGroup,java.lang.String)java.lang.Thread <and> (java.lang.String)ja...
       new Thread( ()  => print( "Hello" ) ).start()


scala> implicit def funcToRunnable( func : () => Unit ) = new Runnable(){ def run() = func() }
funcToRunnable: (() => Unit)java.lang.Object with java.lang.Runnable

scala> def doRun( runnable: Runnable ) = runnable.run
doRun: (Runnable)Unit

scala> doRun( () => print("Hola"))
Hola

scala> new Thread(()=>print("Hello")).start()

scala> Hello
于 2010-06-18T23:54:56.533 に答える
5

実際には、名前による呼び出し引数を使用すると、さらにうまく行うことができます。

implicit def runnable(f: => Unit): Runnable = new Runnable() { def run() = f }

使用法:

import concurrent.ExecutionContext.Implicits.global._
execute(print("hello"))
于 2015-04-20T21:30:55.467 に答える
0

別のスレッドでコードを実行するさらに別の方法:

scala.actors.Actor.actor { ...doSomething()... }
于 2012-05-03T11:54:44.170 に答える