当我发现这段奇怪的代码时,我正在查看sjson的源代码:
<#list 2..22 as i>
<#assign typeParams><#list 1..i as j>T${j}<#if i !=j>,</#if></#list></#assign>
def asProduct${i}[S, ${typeParams}](<#list 1..i as j>f${j}: String<#if i != j>,</#if></#list>)(apply : (${typeParams}) => S)(unapply : S => Product${i}[${typeParams}])(implicit <#list 1..i as j>bin${j}: Format[T${j}]<#if i != j>,</#if></#list>) = new Format[S]{
def writes(s: S) = {
val product = unapply(s)
JsObject(
List(
<#list 1..i as j>
(tojson(f${j}).asInstanceOf[JsString], tojson(product._${j}))<#if i != j>,</#if>
</#list>
))
}
def reads(js: JsValue) = js match {
case JsObject(m) => // m is the Map
apply(
<#list 1..i as j>
fromjson[T${j}](m(JsString(f${j})))<#if i != j>,</#if>
</#list>
)
case _ => throw new RuntimeException("object expected")
}
}
</#list>
乍一看,它看起来像一个宏,但我不确定,因为我看到的是不同的,它们使用 WeakTypeTag 等类修改 Scala AST。我知道这个方法正在生成带有 20 个不同参数列表的 asProduct 方法。但是,当我在我的 REPL 中复制这段代码时,它没有正确解析,并且出现以下错误:
<console>:1: error: identifier expected but double literal found.
还有一堆更多的错误。
我想知道:
- 这种方法为什么以及如何工作
- 更多资源来学习掌握这个
- 为什么在其他库中他们不使用它并且他们更喜欢手动复制/粘贴方法(这实际上是有原因的,还是他们不知道它的存在?)