微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

`Coder[P <: Product]` 的 Scala 2 宏类型类派生以错误结尾`P 不带参数`

如何解决`Coder[P <: Product]` 的 Scala 2 宏类型类派生以错误结尾`P 不带参数`

我是 Scala 2 宏的初学者(在我切换到 Dotty 之前),他在尝试了无形类型类派生后想要更进一步,编写一个可以为任何 {{1} 生成类型类实例的宏没有它。

(为了举例,让我们忽略嵌套的递归类型,所以我的目标是扁平案例类。)

我的类型类是一个抽象类 Coder[T](例如带有 scala.Product / encode() 的 trait)。

所以生成代码为:

decode()

应该是这样的:

case class Pojo(
  s: String,i: Int,l: List[Int]
)

删除了完全指定的类名以提高可读性)

在宏中我尝试:

  • 检查 import com.github.fpopic.scalamacros.Pojo import org.apache.beam.sdk.coders.Coder import java.io.{ByteArrayInputStream,ByteArrayOutputStream} import java.util class PojoCoder extends Coder[Pojo] { import com.github.fpopic.scalamacros.beam.defmacroCoder.{ stringCoder,intCoder,listCoder } override def encode(value: Pojo,os: OutputStream): Unit = { stringCoder.encode(value.s,os) intCoder.encode(value.i,os) listCoder(intCoder).encode(value.l,os) } override def decode(is: InputStream): Pojo = { Pojo( s = stringCoder.decode(is),i = intCoder.decode(is),l = listCoder(intCoder).decode(is) ) } override def getCoderArguments: util.List[_ <: Coder[_]] = { Collections.emptyList() } override def verifyDeterministic(): Unit = () }
  • 迭代每个案例类构造函数字段(weakTypeOf[P] 类型)
    • 隐式找到它们的 typeclass F 实例并将其添加到树中
    • 并将它们的 Coder[F]encode() 表达式附加到有助于最终 decode() 方法的树中。
Coder[P]

但是调用 def materializeProductCoder[P: c.WeakTypeTag](c: blackBox.Context): c.Expr[Coder[P]] = { import c.universe._ val tpe = c.weakTypeOf[P] val helper = new MacrosHelper[c.type](c) val expressions = helper.getPrimaryConstructorMembers(tpe).map { field => val fieldTerm = field.asTerm.name // e.g. value.s (for Now just s) val fieldType = field.typeSignature.finalResultType // e.g. String val fieldCoderName = c.freshName(TermName("coder")) // e.g. give friendly name coder$... val fieldCoderInstance = // e.g. finds instance of Coder[String] c.typecheck( tree = q"""_root_.scala.Predef.implicitly[org.apache.beam.sdk.coders.Coder[${fieldType}]]""",silent = false ) val fieldCoderExpression = q"private val ${fieldCoderName}: org.apache.beam.sdk.coders.Coder[${fieldType}] = ${fieldCoderInstance}" val fieldEncodeExpression = q"${fieldCoderName}.encode(value.${fieldTerm},os)" // replace with full relative name (with dots) instead of value val fieldDecodeExpression = q"${field.asTerm} = ${fieldCoderName}.decode(is)" (fieldCoderExpression,fieldEncodeExpression,fieldDecodeExpression) } val fieldCodersExpression = expressions.map(_._1).distinct val coderEncodeExpresions = expressions.map(_._2) val coderDecodeExpresions = expressions.map(_._3) val coderExpression = q"""{ new org.apache.beam.sdk.coders.Coder[${tpe}] { {import ${c.prefix}._} ..${fieldCodersExpression} override def encode(value: ${tpe},os: java.io.OutputStream): _root_.scala.Unit = { ..${coderEncodeExpresions} } override def decode(is: java.io.InputStream): ${tpe} = { ${tpe.typeConstructor}( ..${coderDecodeExpresions} ) } override def getCoderArguments: java.util.List[_ <: org.apache.beam.sdk.coders.Coder[_]] = { java.util.Collections.emptyList } override def verifyDeterministic(): _root_.scala.Unit = () } } """ val ret = coderExpression c.Expr[Coder[P]](ret) } 后出现错误

(在导入和隐式搜索方面有点挣扎,所以现在有中间 sbt Test / compile,而 distinct 没用)

private val
{
  final class $anon extends org.apache.beam.sdk.coders.Coder[com.github.fpopic.scalamacros.beam.Pojo] {
    def <init>() = {
      super.<init>();
      ()
    };
    {
      import defmacroCoder._;
      ()
    };
    private val coder$macro$1: org.apache.beam.sdk.coders.Coder[String] = scala.Predef.implicitly[org.apache.beam.sdk.coders.Coder[String]](defmacroCoder.stringCoder);
    private val coder$macro$2: org.apache.beam.sdk.coders.Coder[Int] = scala.Predef.implicitly[org.apache.beam.sdk.coders.Coder[Int]](defmacroCoder.intCoder);
    private val coder$macro$3: org.apache.beam.sdk.coders.Coder[List[Int]] = scala.Predef.implicitly[org.apache.beam.sdk.coders.Coder[List[Int]]](defmacroCoder.listCoder[Int](defmacroCoder.intCoder));
    override def encode(value: com.github.fpopic.scalamacros.beam.Pojo,os: java.io.OutputStream): _root_.scala.Unit = {
      coder$macro$1.encode(value.s,os);
      coder$macro$2.encode(value.i,os);
      coder$macro$3.encode(value.l,os)
    };
    override def decode(is: java.io.InputStream): com.github.fpopic.scalamacros.beam.Pojo = com.github.fpopic.scalamacros.beam.Pojo(s = coder$macro$1.decode(is),i = coder$macro$2.decode(is),l = coder$macro$3.decode(is));
    override def getCoderArguments: java.util.List[_$1] forSome { 
      <synthetic> type _$1 <: org.apache.beam.sdk.coders.Coder[_$2] forSome { 
        <synthetic> type _$2
      }
    } = java.util.Collections.emptyList;
    override def verifyDeterministic(): _root_.scala.Unit = ()
  };
  new $anon()
}

我相信哪个来自 here 但不完全理解编译器试图告诉我什么?

可以找到完整代码示例的链接here
可以找到指向 CI 错误链接 here

解决方法

您实例化类的方式是错误的:

${tpe.typeConstructor}(...)

应该是

new $tpe(...)

或者如果你想用 case 类伴随对象的 apply 而不是普通的构造函数来做到这一点:

${tpe.typeSymbol.companion}(...)

注意:类型构造函数(也称为高级类型)与类构造函数

无关

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?