scala 隐式转换为 Runnable?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3073677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:14:12  来源:igfitidea点击:

Implicit conversion to Runnable?

scalarunnableimplicit-conversion

提问by Patrick Arnesen

As an exercise, I tried to create an implicit conversion that would accept a function and produce a Runnable. That way you could call Java methods that accept Runnableobjects and use them like closures.

作为练习,我尝试创建一个隐式转换,它接受一个函数并生成一个Runnable. 这样您就可以调用接受Runnable对象并像使用闭包一样使用它们的Java 方法。

The implicit conversion is easy enough:

隐式转换很简单:

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

However I don't know how to call it. How do you pass in a no-arg function that returns Unit, without having it be evaluated at once? For example, I'd like the following to print "12" but instead it prints "21" because print("2")is evaluated at once.

但是我不知道如何称呼它。您如何传入返回 Unit 的无参数函数,而无需立即对其进行评估?例如,我希望以下内容打印“12”但它打印“21”,因为它print("2")是立即计算的。

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

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

How do I tell the compiler to treat print("2")as the body of a function, not something to be evaluated at once? Some possibilities I tried, such as

我如何告诉编译器将其print("2")视为函数体,而不是立即评估的东西?我尝试过的一些可能性,例如

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

or

或者

    save(=> print("2"))

are not legal syntax.

不是合法的语法。

回答by Patrick Arnesen

arg, just answered my own question. I implemented the implicit conversion incorrectly. The correct implementation is

arg,刚刚回答了我自己的问题。我错误地实现了隐式转换。正确的实现是

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

and you call it like this:

你这样称呼它:

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

This will yield "2"

这将产生“2”

回答by Rex Kerr

If you wanted to live dangerously, you could convert anything to a runnable:

如果你想危险地生活,你可以将任何东西转换为可运行的:

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

Or you could create your own thread-creator-and-starter:

或者您可以创建自己的线程创建器和启动器:

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!

If you wanted to return the thread, then

如果你想返回线程,那么

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

But all of this, while useful, is perhaps even less useful than scala.actors.Futures(tested only on 2.8):

但是所有这些虽然有用,但可能比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!

回答by OscarRyz

Interesting, this way you can execute code that receives a Runnableand pass it a closure.

有趣的是,通过这种方式,您可以执行接收 aRunnable并向其传递闭包的代码。

See:

看:

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

回答by vmolchanov

Actually, you can do it even nicer with call-by-name argument:

实际上,你可以用 call-by-name 参数做得更好:

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

Usage:

用法:

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

回答by jcsahnwaldt says GoFundMonica

Yet another way to run some code in a different thread:

在不同线程中运行一些代码的另一种方法:

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