加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala宏 – 使用`c.prefix`推断隐式值

发布时间:2020-12-16 18:01:30 所属栏目:安全 来源:网络整理
导读:c.inferImplicitValue推断出调用站点范围中的隐式值.是否可以使用c.prefix范围推断出implicits? 这不是有效的代码,但表达了我的需要: c.prefix.inferImplicitValue 我目前正在为此目的使用一个天真的实现[1],但它有一些限制,例如不从defs推断隐含值并检测
c.inferImplicitValue推断出调用站点范围中的隐式值.是否可以使用c.prefix范围推断出implicits?

这不是有效的代码,但表达了我的需要:

c.prefix.inferImplicitValue

我目前正在为此目的使用一个天真的实现[1],但它有一些限制,例如不从defs推断隐含值并检测重复/模糊隐含值.

[1] https://github.com/getquill/quill/blob/9a28d4e6c901d3fa07e7d5838e2f4c1f3c16732b/quill-core/src/main/scala/io/getquill/util/InferImplicitValueWithFallback.scala#L12

解决方法

只需生成一个具有适当(本地)导入的块,然后调用隐式执行操作:

q"""{import ${c.prefix}._; _root_.scala.Predef.implicitly[$T] }

其中T是Type的实例,表示要查找的隐式值的类型.

要检查隐式查找是否实际成功,可以使用silent = true调用Context.typeCheck并检查生成的树是否为空.

作为一个例子,这里是一个实现一个推断方法的例子,如果在目标对象的成员中找不到隐式,则返回None,否则将结果包装在Some中.

import scala.reflect.macros.Context
import scala.language.experimental.macros

def inferImplicitInPrefixContext[T:c.WeakTypeTag](c: Context): c.Tree = {
  import c.universe._
  val T = weakTypeOf[T]
  c.typeCheck(
    q"""{
      import ${c.prefix}._
      _root_.scala.Predef.implicitly[$T]
    }""",silent = true
  )
}

def infer_impl[T:c.WeakTypeTag](c: Context): c.Expr[Option[T]] = {
  import c.universe._
  c.Expr[Option[T]](
    inferImplicitInPrefixContext[T](c) match {
      case EmptyTree => q"_root_.scala.None"
      case tree => q"_root_.scala.Some($tree)"
    }
  )
}

trait InferOp {
  def infer[T]: Option[T] = macro infer_impl[T]
}

我们来测试一下:

object Foo extends InferOp {
  implicit val s = "hello"
}

Foo.infer[String] // res0: Some[String] = Some(hello)

Foo.infer[Int] // res1: None.type = None

implicit val lng: Long = 123L

Foo.infer[Long] // res2: Some[Long] = Some(123)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读