/ / Implicit conversion to Runnable? - скала, runnable, implicit-conversion

Импресионното преобразуване в Runnable? - скала, runnable, implicit-conversion

Като упражнение се опитах да създам имплицитно преобразуване, което да приеме функция и да произведе а Runnable, По този начин можете да се обадите на Java методи, които приемат Runnable обекти и ги използват като затварящи устройства.

Заключеното преобразуване е достатъчно лесно:

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

Но не знам как да го нарека. Как преминавате в функция no-arg, която връща единица, без да я оценявате веднага? Например, бих искал следното да отпечатате "12", но вместо това той отпечатва "21", защото print("2") се оценява едновременно.

    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"))

не са юридически синтаксис.

Отговори:

23 за отговор № 1

arg, просто отговори на моя въпрос. Въведох имплицитната конверсия неправилно. Правилното внедряване е

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

и го наричате така:

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

Това дава "12"


12 за отговор № 2

Ако искаш да живееш опасно, можеш да преобразуваш всичко в едно:

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!

5 за отговор № 3

Интересно, по този начин можете да изпълните код, който получава a 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

4 за отговор № 4

Всъщност можете да го направите още по-хубаво с аргумента за име-на-име:

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

Начин на употреба:

import concurrent.ExecutionContext.Implicits.global._
execute(print("hello"))

0 за отговор № 5

Още един начин да изпълните някой код в друга нишка:

scala.actors.Actor.actor { ...doSomething()... }