部分将有一个隐含的参数的函数(Partially applying a function that

2019-09-02 02:51发布

我能把这需要一个隐含的参数成函数的方法?

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
}

我发现这个问题 ,但它不与方法的功能提升,据我所看到的处理。

Answer 1:

Implicits仅供方法的工作。 但是你要传递给函数withSelection 。 您可以通过包装在一个函数的方法得到解决:

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

它不可能通过deleteObjects直接,因为foo _不为工作foo与定义的隐含参数列表。



Answer 2:

据我所知,隐含的分辨率必须发生在使用网站,并不能令行禁止了。 当我试图解决'ExecutionContext'增殖在我的代码我自己失望的时刻了。

我一直在考虑一个妥协是:

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

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

该'implicit'只能在函数中持有 - 我们必须在调用妥协:

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 transactional'我曾经'def async'。

然而,我对此感到遗憾,因为它复杂的继承,并造成一些分配开销(尽管这应该JIT编译的距离)。

底线是,你必须拿出你的调用函数的更明确的零碎方法 - 一个比单独讨好那么优雅。



文章来源: Partially applying a function that has an implicit parameter