【发布时间】:2019-07-23 15:41:30
【问题描述】:
我目前正在开发的一个应用程序是使用scala-cats'IOApp 以函数式编程风格编写的。
现在的问题是我需要将这个应用程序部署在一个似乎并不真正适合我的功能方法的 OSGi 上下文中。
我的主要方法是这样的:
object Main extends IOApp {
override def run(args: List[String]): IO[ExitCode] = for {
_ <- IO(println("Starting with args: " + args.mkString(",")))
myProgram = new MyProgram(/*...*/)
_ <- myProgram.run() // def run(): IO[RunResult]
// ...
_ <- myProgram.exit() // def exit(): IO[Unit]
} yield ExitCode.Success
}
现在要将它部署到 OSGi,我必须写一个 BundleActivator:
import org.osgi.framework.{BundleActivator, BundleContext}
class Activator extends BundleActivator {
private var myProgram: Option[myProgram] = None
override def start(context: BundleContext): Unit = {
myProgram = Some(new MyProgram(/*...*/))
myProgram.foreach{ _.run().unsafeRunSync() }
}
override def stop(context: BundleContext): Unit = {
myProgram.foreach{ _.exit().unsafeRunSync() }
}
}
如您所见,我想出的Activator 远非以功能性方式编写。有什么办法至少可以摆脱var myProgram(具体来说是可变的var)?我似乎无法弄清楚这怎么可能。
编辑:
激活器需要在manifest中定义,所以这是我build.sbt的一部分:
packageOptions := Seq(ManifestAttributes(
("Bundle-Activator", "my.package.Activator"),
...))
【问题讨论】:
-
考虑定制一个
cats.effect.Resource来代表BundleActivator` -
另外,我仍然明白为什么您使用
var和Option。IO很懒。 -
@V-Lamp 你说的没有道理。您将不得不指向清单中的激活器,那么
Resource是从哪里来的?IO的懒惰与这里使用var或Option有什么关系? -
我的 cmets 在显示
packageOptions的编辑之前,我现在看到它没有意义 :) -
澄清一下:上面的代码运行良好!在我看来,这还不够“纯”/FP。
标签: scala functional-programming osgi scala-cats io-monad