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

scala – 路径依赖类型和嵌套特征

发布时间:2020-12-16 19:09:16 所属栏目:安全 来源:网络整理
导读:背景 假设我有一些嵌套的特征: trait Foo { trait Bar } 还有几个例子: val myFoo = new Foo {}val myBar = new myFoo.Bar {} 我可以写下面的内容(至少一目了然),就像他们应该做的或多或少相同的事情: def whatever1(foo: Foo)(bar: foo.Bar) = bardef wh
背景

假设我有一些嵌套的特征:

trait Foo { trait Bar }

还有几个例子:

val myFoo = new Foo {}
val myBar = new myFoo.Bar {}

我可以写下面的内容(至少一目了然),就像他们应该做的或多或少相同的事情:

def whatever1(foo: Foo)(bar: foo.Bar) = bar
def whatever2(foo: Foo): foo.Bar => foo.Bar = { bar => bar }
def whatever3(foo: Foo) = new { def apply(bar: foo.Bar) = bar }
case class whatever4(foo: Foo) { def apply(bar: foo.Bar) = bar }
case class whatever5[F <: Foo](foo: F) { def apply(bar: foo.Bar) = bar }

请注意,最后一个灵感来自于here的解决方案.

前三项工作:

scala> val sameBar1: myFoo.Bar = whatever1(myFoo)(myBar)
sameBar1: myFoo.Bar = $anon$1@522f63e7

scala> val sameBar2: myFoo.Bar = whatever2(myFoo)(myBar)
sameBar1: myFoo.Bar = $anon$1@522f63e7

scala> val sameBar3: myFoo.Bar = whatever3(myFoo)(myBar)
sameBar2: myFoo.Bar = $anon$1@522f63e7

但不是第四或第五:

scala> val sameBar4: myFoo.Bar = whatever4(myFoo)(myBar)
<console>:12: error: type mismatch;
 found   : myFoo.Bar
 required: _1.foo.Bar where val _1: whatever4
       val sameBar4: myFoo.Bar = whatever4(myFoo)(myBar)
                                                  ^

很公平 – 我们不能做以下任何一个,可能是类似的原因:

scala> val myOof = myFoo
myOof: Foo = $anon$1@39e4ff0c

scala> val myOofBar: myOof.Bar = new myFoo.Bar {}
<console>:10: error: type mismatch;
 found   : myFoo.Bar
 required: myOof.Bar
       val myOofBar: myOof.Bar = new myFoo.Bar {}
                                 ^

无论如何,由于我们有三个工作解决方案,这并不重要.

问题

(首先我要注意的是,当我在使用宏时遇到下面的问题,而我的例子在这里涉及到反射API,我的问题不是特定于宏或反射.)

假设我正在使用新的反思API,并希望能够编写以下内容:

applier[List[_]](Literal(Constant(42)),Literal(Constant(13)))

并且它的意思是“给我列表(42,13)的抽象语法树”.这不是太难了 – 我只能使用上面的任何3的方法:

trait ReflectionUtils {
  import scala.reflect.api.Universe
?
  def companionApplier(u: Universe) = new {
    def apply[A: u.TypeTag](xs: u.Tree*): u.Tree = u.Apply(
      u.Select(u.Ident(u.typeOf[A].typeSymbol.companionSymbol),"apply"),xs.toList
    )
  }
}

现在我得到我想要的语法(见我的answer到this question更详细的动机的例子):

object MacroExample extends ReflectionUtils {
  import scala.language.experimental.macros
  import scala.language.reflectiveCalls
  import scala.reflect.macros.Context

  def threeOfThem(n: Int) = macro threeOfThem_impl
  def threeOfThem_impl(c: Context)(n: c.Expr[Int]) = {
    val applier = companionApplier(c.universe)

    c.Expr[List[Int]](applier[List[_]](n.tree,n.tree,n.tree))
  }
}

一切都按照预期工作.不过,我并不喜欢“结构型会员”的反思性访问.不幸的是,我不能使用这里的任何1或任何2的方法,因为当我将这个东西应用到我的宇宙时,我无法修复类型参数.我很想写下列内容:

case class companionApplier(u: Universe) {
  def apply[A: u.TypeTag](xs: u.Tree*): u.Tree = u.Apply(
    u.Select(u.Ident(u.typeOf[A].typeSymbol.companionSymbol),xs.toList
  )
}

但是,这当然会让我陷入以上所有类似的类型不匹配问题.

有没有其他的技巧我失踪了?我可以在不使用具有结构类型成员的匿名类的情况下获得所需的语法吗?

解决方法

这应该工作:

case class companionApplier[U <: Universe](u: U) { ... }

// in macro
companionApplier[c.universe.type](c.universe)

几个月前我也有类似的问题,见here.

(编辑:李大同)

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

    推荐文章
      热点阅读