Search code examples
scalaimplicit

Will Scala support detect implicit parameter from caller rather then from definition?


Maybe it's a foolish question but I think the usage is reasonable and useful more then current way to detect implicit parameter.
There is a example what's the means of detect implicit parameter from caller, give the code first:

package tagedfuture

class Future[+T](f: => T)(implicit tag: String) {

  def map[B](f2: T => B): Future[B] = {
    Future(f2(f))
  }

  def flatMap[B](f2: T => Future[B]): Future[B] = {
    f2(f)
  }

  def getTag = tag
}

object Future {
  def apply[T](f: => T)(implicit tag: String): Future[T] = new Future(f)

}

object Test extends App {
  val fur = Future{
    10
  }("future-chain-1")

  val fur2 = fur.map(x => x * 2)

  val fur3 = fur2.flatMap(x => {
    anotherFuture(x)(fur2.getTag)
    // expect this:
    // anotherFuture(x)
  })

  def anotherFuture(int: Int)(implicit tag: String): Future[String] = {
    Future(int.toString)
  }

  // expect this:
  //def anotherFuture(int: Int): Future[String] = {
  //  Future(int.toString)
  //}

  assert(fur.getTag == fur2.getTag && fur2.getTag == fur3.getTag)
}

tagedfuture.Future.apply expect a implicit parameter used to tag where the Future instance come from.
In anotherFuture method, it can complied, which has a implicit tag: String parameter for transfer the tag when generate a new Future.

We must append the implicit parameter for anotherFuture because compiler detect the method context which from import package, class definition place. but not verify by it's caller.

how about support detect implicit from caller?
We can use //expect this: which remove all implicit boilerplate code. Even through we removed it, we can get implicit instance from caller in which is first Future fur1's "future-chain-1".

It seems more difficult then current implement. Will Scala support this way to use implicit?

UPDATE

What's exactly means of detect by caller in terms of compiler workflow?

Currently, when we defined a method which it use a method has a implicit parameter, like def anotherFuture, compiler will check the method context which contains import pacakge, implicit variable in relative class/object definition and report error if not any implicit to match the method need.
detect by caller means compiler not check the place of the method definition place but check the caller place where invoke the method. At this stage, the caller place is anotherFuture(x)(fur2.getTag). The context contains Test object, fur2 instance and flatmap method.
I'm expect it will be compiled by detect the fur2 instance where has a tag variable.

It's different then before but at this stage it can find the implicit by the way and give a elegant code to transfer the implicit context.


Solution

  • To recap, you want the compiler to inspect every variable in scope (at the place where a method with an implicit parameter is called) looking for any (public) member of its class that is itself marked as implicit and matching the expected type, in order to provide it to the called method as an argument to the implicit parameter.

    I think this would be highly ambiguous (which implicit do you choose if you have two instances of Future[X] in scope?), slow down the compiler considerably and would simply not be manageable for the human brain.

    So, my answer would be no. (if I understood your question correctly)