Pat*_*sen 17 scala implicit-conversion runnable
作为练习,我尝试创建一个隐式转换,它将接受一个函数并生成一个Runnable.这样你就可以调用接受Runnable对象的Java方法,并像封闭一样使用它们.
隐式转换很容易:
implicit def funToRunnable(fun : Unit) = new Runnable() { def run = fun }
Run Code Online (Sandbox Code Playgroud)
但是我不知道怎么称呼它.如何传入一个返回Unit的无参数函数,而不是立即进行评估?例如,我想要以下内容来打印"12",而是打印"21"因为print("2")一次评估.
var savedFun : Runnable = null
def save(r : Runnable) = { savedFun = r }
save(print("2"))
print("1")
savedFun.run()
Run Code Online (Sandbox Code Playgroud)
如何告诉编译器将其print("2")视为函数的主体,而不是立即进行评估?我试过的一些可能性,比如
save(() => print("2"))
Run Code Online (Sandbox Code Playgroud)
要么
save(=> print("2"))
Run Code Online (Sandbox Code Playgroud)
不是合法的语法.
Pat*_*sen 23
arg,刚刚回答了我自己的问题.我错误地实现了隐式转换.正确的实施是
implicit def funToRunnable(fun: () => Unit) = new Runnable() { def run() = fun() }
Run Code Online (Sandbox Code Playgroud)
你这样称呼它:
save(() => print("2"))
Run Code Online (Sandbox Code Playgroud)
这将产生"2"
Rex*_*err 12
如果你想危险地生活,你可以将任何东西转换成可运行的东西:
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
Run Code Online (Sandbox Code Playgroud)
或者你可以创建自己的线程创建者和启动者:
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!
Run Code Online (Sandbox Code Playgroud)
如果你想返回线程,那么
def thread[F](f: => F) = {
val t = new Thread( new Runnable() { def run() { f } } )
t.start()
t
}
Run Code Online (Sandbox Code Playgroud)
但所有这一切虽然有用,但可能没有那么有用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!
Run Code Online (Sandbox Code Playgroud)
有趣的是,通过这种方式,您可以执行接收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
Run Code Online (Sandbox Code Playgroud)
小智 5
实际上,您可以使用call-by-name参数来做得更好:
implicit def runnable(f: => Unit): Runnable = new Runnable() { def run() = f }
Run Code Online (Sandbox Code Playgroud)
用法:
import concurrent.ExecutionContext.Implicits.global._
execute(print("hello"))
Run Code Online (Sandbox Code Playgroud)