16

我可以将采用隐式参数的方法转换为函数吗?

trait Tx

def foo(bar: Any)(implicit tx: Tx) {}

foo _ // error: could not find implicit value for parameter tx: Tx

我正在尝试实现以下目标,最好是如果我能以某种方式使其与普通调用一起工作withSelection(deleteObjects)

trait Test {      
  def atomic[A](fun: Tx => A): A

  def selection: Iterable[Any]

  def withSelection(fun: Iterable[Any] => Tx => Unit) {
    val sel = selection
    if (sel.nonEmpty) atomic { implicit tx =>
      fun(sel)(tx)
    }
  }

  object deleteAction {
    def apply() {
      withSelection(deleteObjects)  // !
    }
  }

  def deleteObjects(xs: Iterable[Any])(implicit tx: Tx): Unit
}

我发现了这个问题,但是据我所知,它不涉及从方法到功能的提升。

4

2 回答 2

8

隐式仅适用于方法。但是你必须将一个函数传递给withSelection. 您可以通过将方法包装在函数中来解决:

withSelection(a => b => deleteObjects(a)(b))

它不可能deleteObjects直接传递,因为对于定义了隐式参数列表foo _的 a 不起作用。foo

于 2013-05-07T08:21:08.357 回答
4

据我所知,隐式解决必须在使用现场进行,并且不能被取消。我自己的失望时刻是当我试图在我的代码中解决“ExecutionContext”扩散问题时。

我一直在考虑的一种折衷方案是:

type Async[A] = ExecutionContext => Future[A]

def countFiles(root: String): Async[Int] = implicit ec =>
  // ...

“隐式”只存在于函数中——我们必须在调用上妥协:

implicit class AsyncExt[A](async: Async[A]) {
  def invoke()(implicit ec: ExecutionContext) = async(ec)
}

implicit val ec = ...
countFiles("/").invoke()

另一种妥协——我选择并活到后悔的那个:

class AsyncFileCounter(ec: ExecutionContext) {
  def countFiles(root: String): Future[A] = ...
}

class FileCounter {
  def async(implicit ec: ExecutionContext) = new AsyncFileCounter(ec)
}

这改变了天真的用法(但需要):

implicit val ec = ...
val counter = new FileCounter
counter.countFiles("/") // <-- nope

到以下:

implicit val ec = ...
val counter = new FileCounter
counter.async.countFiles("/") // yep!

根据您的上下文,这可能是可以忍受的。你可以在我使用“def async”的地方添加一个“def transactional”。

然而,我确实对此感到遗憾,因为它使继承复杂化,并产生了一些分配开销(尽管应该 JIT 去掉)。

底线是你必须想出一个更明确的零碎的方法来调用你的函数——一个比单独柯里化更不优雅的方法。

于 2013-05-07T08:55:24.300 回答