Scala 是否支持从调用者而不是定义中检测隐式参数?
Will Scala support detect implicit parameter from caller rather then from definition?
也许这是个愚蠢的问题,但我认为这种用法比当前检测隐式参数的方法更合理、更有用。
有一个例子是什么方法检测来自调用者的隐式参数,先给出代码:
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
期望一个隐式参数用于标记 Future 实例的来源。
在anotherFuture
方法中,它可以编译,其中有一个implicit tag: String
参数,用于在生成新的Future时传递标签。
我们必须为 anotherFuture
附加隐式参数,因为编译器会检测来自 import package
、class 定义位置的方法上下文。但不通过调用者验证。
如何支持从调用者检测隐式?
我们可以使用 //expect this:
删除所有隐式样板代码。即使我们删除了它,我们也可以从调用者那里获得隐式实例,其中第一个 Future
fur1 的 "future-chain-1"
.
感觉比现在的实现难度大。 Scala 会支持这种隐式使用方式吗?
更新
在编译器工作流程方面,调用者检测的确切方法是什么?
目前,当我们定义一个方法时,它使用一个方法有一个隐式参数,比如def anotherFuture
,编译器会检查包含import pacakge
的方法上下文,
相对 class/object 定义中的隐式变量,如果没有隐式匹配方法需要则报告错误。
通过调用者检测意味着编译器不检查方法定义位置的位置,而是检查调用方法的调用者位置。现阶段,来电地点为anotherFuture(x)(fur2.getTag)
。上下文包含 Test
对象、fur2
实例和 flatmap
方法。
我希望它将通过检测具有 tag
变量的 fur2
实例来编译。
和以前不一样,不过在这个阶段可以顺便找到隐式,给出一个优雅的代码来传递隐式上下文。
总而言之,您希望编译器检查范围内的每个变量(在调用具有隐式参数的方法的地方)寻找 any (public) 其 class 的成员本身标记为隐式并匹配预期类型,以便将其作为隐式参数的参数提供给被调用方法。
我认为这会非常含糊(如果范围内有两个 Future[X]
实例,您会选择哪个隐式?),会大大降低编译器的速度,而且人脑根本无法管理。
所以,我的回答是否定的。 (如果我正确理解你的问题)
也许这是个愚蠢的问题,但我认为这种用法比当前检测隐式参数的方法更合理、更有用。
有一个例子是什么方法检测来自调用者的隐式参数,先给出代码:
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
期望一个隐式参数用于标记 Future 实例的来源。
在anotherFuture
方法中,它可以编译,其中有一个implicit tag: String
参数,用于在生成新的Future时传递标签。
我们必须为 anotherFuture
附加隐式参数,因为编译器会检测来自 import package
、class 定义位置的方法上下文。但不通过调用者验证。
如何支持从调用者检测隐式?
我们可以使用 //expect this:
删除所有隐式样板代码。即使我们删除了它,我们也可以从调用者那里获得隐式实例,其中第一个 Future
fur1 的 "future-chain-1"
.
感觉比现在的实现难度大。 Scala 会支持这种隐式使用方式吗?
更新
在编译器工作流程方面,调用者检测的确切方法是什么?
目前,当我们定义一个方法时,它使用一个方法有一个隐式参数,比如def anotherFuture
,编译器会检查包含import pacakge
的方法上下文,
相对 class/object 定义中的隐式变量,如果没有隐式匹配方法需要则报告错误。
通过调用者检测意味着编译器不检查方法定义位置的位置,而是检查调用方法的调用者位置。现阶段,来电地点为anotherFuture(x)(fur2.getTag)
。上下文包含 Test
对象、fur2
实例和 flatmap
方法。
我希望它将通过检测具有 tag
变量的 fur2
实例来编译。
和以前不一样,不过在这个阶段可以顺便找到隐式,给出一个优雅的代码来传递隐式上下文。
总而言之,您希望编译器检查范围内的每个变量(在调用具有隐式参数的方法的地方)寻找 any (public) 其 class 的成员本身标记为隐式并匹配预期类型,以便将其作为隐式参数的参数提供给被调用方法。
我认为这会非常含糊(如果范围内有两个 Future[X]
实例,您会选择哪个隐式?),会大大降低编译器的速度,而且人脑根本无法管理。
所以,我的回答是否定的。 (如果我正确理解你的问题)