Scala酸洗和类型参数

emc*_*sen 7 scala scala-pickling

我正在使用Scala Pickling,一个Scala的自动序列化框架.根据作者的幻灯片,T只要有隐含Pickler[T]的范围,任何类型都可以被腌制.在这里,我假设她的意思scala.tools.nsc.io.Pickler.但是,以下内容无法编译:

import scala.pickling._
import scala.pickling.binary._
import scala.tools.nsc.io.Pickler

object Foo {
  def bar[T: Pickler](t: T) = t.pickle
}
Run Code Online (Sandbox Code Playgroud)

错误是:

[error] exception during macro expansion:
[error] scala.ScalaReflectionException: type T is not a class
[error]     at scala.reflect.api.Symbols$SymbolApi$class.asClass(Symbols.scala:323)
[error]     at scala.reflect.internal.Symbols$SymbolContextApiImpl.asClass(Symbols.scala:73)
[error]     at scala.pickling.PickleMacros$class.pickleInto(Macros.scala:381)
[error]     at scala.pickling.Compat$$anon$17.pickleInto(Compat.scala:33)
[error]     at scala.pickling.Compat$.PickleMacros_pickleInto(Compat.scala:34)
Run Code Online (Sandbox Code Playgroud)

我正在使用Scala 2.10.2与scala-pickling 0.8-SNAPSHOT.

这是错误还是用户错误?

编辑1:同样的错误既出现scala.pickling.SPicklerscala.pickling.DPickler.

编辑2:看起来这是一个错误:https://github.com/scala/pickling/issues/31

Hea*_*ler 10

是的,安迪指出:

你需要a scala.pickling.SPickler或a scala.pickling.DPickler(分别是静态和动态)来挑选特定的类型.

这些都已经包含在scala.pickling包中,因此只需在通用方法签名中使用它们即可.

您可以SPickler向泛型方法添加上下文绑定,这是完全正确的.你需要的唯一额外的东西(诚然,它有点难看,我们正在考虑删除它)是添加一个FastTypeTag上下文绑定.(这对于酸洗框架来说是必要的,以了解它试图腌制的类型,例如,它以不同的方式处理基元.)

这是您需要做的提供通用酸洗/去除方法的方法:

请注意,对于该unbar方法,您需要提供Unpickler上下文绑定而不是SPickler上下文绑定.

import scala.pickling._
import binary._

object Foo {
  def bar[T: SPickler: FastTypeTag](t: T) = t.pickle
  def unbar[T: Unpickler: FastTypeTag](bytes: Array[Byte]) = bytes.unpickle[T]
}
Run Code Online (Sandbox Code Playgroud)

在REPL中测试这个,你会得到:

scala> Foo.bar(42)
res0: scala.pickling.binary.BinaryPickle =
BinaryPickle([0,0,0,9,115,99,97,108,97,46,73,110,116,0,0,0,42])

scala> Foo.unbar[Int](res0.value)
res1: Int = 42
Run Code Online (Sandbox Code Playgroud)

  • 使用酸洗库时,DPickler会在哪里发挥作用? (2认同)