如何显式传递隐式参数?
How to pass implicit parameter explicitly?
如果我们定义如下函数:
def methodWithImplicit(explicit: String)(implicit imp: String) = {
println(explicit + imp)
}
我们可以这样称呼它:
methodWithImplicit("abc")("efg") //abc - explicit, efg - imp
而且效果很好。现在考虑以下类型类:
trait MyTypeClass[T] {
def accept(t: T): T
}
将在提取器对象中使用:
object TestExtractor {
def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
if (!str.isEmpty)
Some(myTypeClass.accept(str))
else
None
}
所以如果我们这样使用它:
implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
override def accept(t: String): Unit = t
}
"123" match {
case TestExtractor(str) => println(str)
}
它工作正常。但是如何在使用模式匹配时显式传递参数?我试过了
"123" match {
case TestExtractor(str)(myTypeClass) => println(str) //compile error
}
和
"123" match {
case TestExtractor(myTypeClass)(str) => println(str) //compile error
}
但是编译不了。
由于左侧似乎基本上只接受由稳定标识符、常量文字和变量名的 lower-case 字母构建的树,我看不出有任何方法可以更接近所需的语法比这个:
val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)
"hello" match {
case `TestExtractor(myTypeClass)`(str) => println(str)
}
这当然需要您在 match-case 之前定义奇怪的命名值 TestExtractor(myTypeClass)
(反引号),这样您就可以将它用作单个符号。
完整代码:
trait MyTypeClass[T] {
def accept(t: T): T
}
object TestExtractor { outer =>
def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
if (!str.isEmpty)
Some(myTypeClass.accept(str))
else
None
class ExplicitTestExtractor(tc: MyTypeClass[String]) {
def unapply(t: String) = outer.unapply(t)(tc)
}
def apply(tc: MyTypeClass[String]): ExplicitTestExtractor =
new ExplicitTestExtractor(tc)
}
implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
override def accept(t: String): String = t.toUpperCase
}
val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)
"hello" match {
case `TestExtractor(myTypeClass)`(str) => println(str)
}
如果我们定义如下函数:
def methodWithImplicit(explicit: String)(implicit imp: String) = {
println(explicit + imp)
}
我们可以这样称呼它:
methodWithImplicit("abc")("efg") //abc - explicit, efg - imp
而且效果很好。现在考虑以下类型类:
trait MyTypeClass[T] {
def accept(t: T): T
}
将在提取器对象中使用:
object TestExtractor {
def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
if (!str.isEmpty)
Some(myTypeClass.accept(str))
else
None
}
所以如果我们这样使用它:
implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
override def accept(t: String): Unit = t
}
"123" match {
case TestExtractor(str) => println(str)
}
它工作正常。但是如何在使用模式匹配时显式传递参数?我试过了
"123" match {
case TestExtractor(str)(myTypeClass) => println(str) //compile error
}
和
"123" match {
case TestExtractor(myTypeClass)(str) => println(str) //compile error
}
但是编译不了。
由于左侧似乎基本上只接受由稳定标识符、常量文字和变量名的 lower-case 字母构建的树,我看不出有任何方法可以更接近所需的语法比这个:
val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)
"hello" match {
case `TestExtractor(myTypeClass)`(str) => println(str)
}
这当然需要您在 match-case 之前定义奇怪的命名值 TestExtractor(myTypeClass)
(反引号),这样您就可以将它用作单个符号。
完整代码:
trait MyTypeClass[T] {
def accept(t: T): T
}
object TestExtractor { outer =>
def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
if (!str.isEmpty)
Some(myTypeClass.accept(str))
else
None
class ExplicitTestExtractor(tc: MyTypeClass[String]) {
def unapply(t: String) = outer.unapply(t)(tc)
}
def apply(tc: MyTypeClass[String]): ExplicitTestExtractor =
new ExplicitTestExtractor(tc)
}
implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
override def accept(t: String): String = t.toUpperCase
}
val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)
"hello" match {
case `TestExtractor(myTypeClass)`(str) => println(str)
}