Partially applying a function that has an implicit parameter

前端 未结 2 908
南方客
南方客 2021-01-04 01:42

Can I turn a method which takes an implicit parameter into a function?

trait Tx

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

foo _ // error: could not find implic         


        
相关标签:
2条回答
  • 2021-01-04 02:06

    Implicits only work for methods. But you have to pass a function to withSelection. You can get around by wrapping the method in a function:

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

    Its impossible to pass deleteObjects directly because foo _ does not work for a foo with an implicit parameter list defined.

    0 讨论(0)
  • 2021-01-04 02:20

    To the best of my knowledge, implicit resolution must take place at usage site, and cannot be curried away. My own moment of disappointment was when I was trying to work around ´ExecutionContext´ proliferation in my code.

    One compromise I've been considering was:

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

    The ´implicit´ only holds within the function -- we have to compromise on invocation:

    implicit class AsyncExt[A](async: Async[A]) {
      def invoke()(implicit ec: ExecutionContext) = async(ec)
    }
    
    implicit val ec = ...
    countFiles("/").invoke()
    

    Another compromise -- the one I chose and lived to regret:

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

    This changes the usage from the naive (but desired):

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

    To the following:

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

    Depending on your context, this could be bearable. You could add a ´def transactional´ where I used ´def async´.

    I do regret this however, as it complicates inheritance, and incurs some allocation overhead (though that should be JITed away).

    Bottom line is that you'll have to come up with a more explicit piecemeal method of invoking your function -- one that is less elegant than currying alone.

    0 讨论(0)
提交回复
热议问题