2015-09-25 70 views
2

我有一类这样看,定义`Codec`递归数据结构

case class Foo (bar: Int, foos: Vector[Foo]) 

定义Codec[Foo],我想这一点,

def fc = shapeless.Lazy((int32 ~~ vector(fc)).widenOpt((Foo.apply _).tupled, Foo.unapply _)) 

但这并没有工作,因为scodec投掷StackOverflowError。这样做的正确方法是什么?

回答

3

你需要的scodec.codecs.lazily组合子建递归编解码器(不shapeless.lazily)。例如:

scala> def fc: Codec[Foo] = lazily((int32 :: vector(fc)).as[Foo]) 
fc: scodec.Codec[Foo] 

scala> val res = fc.encode(Foo(1, Vector(Foo(2, Vector.empty)))).require 
res: scodec.bits.BitVector = BitVector(64 bits, 0x0000000100000002) 

scala> fc.decode(res) 
res2: scodec.Attempt[scodec.DecodeResult[Foo]] = Successful(DecodeResult(Foo(1,Vector(Foo(2,Vector()))),BitVector(empty))) 

在scodec 1.8.2和之前,导出该编解码器,而不是在编译时显式地定义它,导致错误时,由于导出继续递归地永远。从1.8.3开始,这个编解码器可以自动派生而没有问题。

对于递归树的一个例​​子,看到this example from scodec source

+0

感谢您的建议。我尝试过,但仍然以国有企业而告终。事实上,即使我给没有引起编译错误的原始定义,只有当我试图在运行时将其打印在控制台中,过程与国有企业 – Sheng

+0

崩溃将是巨大的,如果scodec能够提供某种形式的例子说明如何为树形数据结构创建一个编解码器。我认为我的问题归结为这一点。 – Sheng

+0

但这会在运行时抛出SOE。 def fc:Codec [Foo] = {import shapeless._; lazily((int32 :: vector(fc))。as [Foo])}有什么区别? – Sheng