Scala 部分应用具有隐式参数的函数

Scala 部分应用具有隐式参数的函数,scala,implicit,currying,partial-application,Scala,Implicit,Currying,Partial Application,我可以把一个隐式参数转换成函数吗 trait Tx def foo(bar: Any)(implicit tx: Tx) {} foo _ // error: could not find implicit value for parameter tx: Tx 我正在尝试实现以下目标,如果我能够以某种方式使其与SelectionDeleteObjects的普通调用一起工作,则更好: 然而,据我所知,它并没有处理从方法到函数的提升。这意味着它只适用于方法。但是你必须通过一个函数来进行选择。您

我可以把一个隐式参数转换成函数吗

trait Tx

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

foo _ // error: could not find implicit value for parameter tx: Tx
我正在尝试实现以下目标,如果我能够以某种方式使其与SelectionDeleteObjects的普通调用一起工作,则更好:


然而,据我所知,它并没有处理从方法到函数的提升。

这意味着它只适用于方法。但是你必须通过一个函数来进行选择。您可以通过将方法包装到函数中来实现:

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

直接传递deleteObjects是不可能的,因为foo不适用于定义了隐式参数列表的foo。

据我所知,隐式解析必须在使用站点进行,并且不能立即执行。我自己感到失望的时刻是当我试图解决代码中的“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
根据你的背景,这可能是可以忍受的。您可以在我使用def async的地方添加一个“def transactional”

然而,我确实对此感到遗憾,因为这会使继承复杂化,并且会产生一些分配开销,尽管这应该被jit处理掉


底线是,你必须想出一个更明确的逐段调用函数的方法——一个比单独使用curry更不优雅的方法。

关于第二种情况,即FileCounter,你不能定义一个隐式转换隐式def counterToAsyncc:FileCounter:AsyncFileCounter=c.async,这样你就可以再次counter.countFiles/?很好!在我的例子中,隐式转换将被包含对象上具有类似签名的同步方法所击败。然而,这绝对是一个很好的样板解决方案!不过,我确实需要验证escape分析是否确实消除了异步对象的堆分配。我想说的是,同步方法将具有不同的签名,因为它们不会返回将来的[a],而只是返回一个a,因此编译器可以告诉您这一点。您应该简单地在需要异步调用的地方划定范围,并在那里导入隐式转换。至于避免堆分配,我不能打赌……唉,Scala不支持仅基于返回值的方法重载。尽管如此,您建议的隐式转换在许多情况下都是有用的。关于堆分配-一旦JIT确定'Async'对象从未离开它不应该离开的堆栈帧,那么JIT将确保它只分配给堆栈而不是堆。感谢您的解释
implicit val ec = ...
val counter = new FileCounter
counter.countFiles("/") // <-- nope
implicit val ec = ...
val counter = new FileCounter
counter.async.countFiles("/") // yep!