在kiama中,通用“dup”方法is defined复制Product
个对象并将给定函数应用于Product
的每个元素以支持重写Term
s:
/**
* General product duplication function. Returns a product that applies
* the same constructor as the product t, but with the given children
* instead of t's children. Fails if a constructor cannot be found or
* if one of the children is not of the appropriate type.
*/
private def dup (t : Product, children : Array[AnyRef]) : Product = {
val ctor = (t.getClass.getConstructors())(0)
try {
val ret = ctor.newInstance (children : _*).asInstanceOf[Product]
ret
} catch {
case e : java.lang.ClassCastException =>
error ("dup cast failed: " + t)
case e : IllegalArgumentException =>
error ("dup illegal arguments: " + ctor + " (" +
children.deep.mkString (",") + "), expects " +
ctor.getParameterTypes.length)
}
}
使用like this:
private def childProduct (p : Product, i : Int, s : => Strategy) : Option[Term] = {
val numchildren = p.productArity
val ct = p.productElement (i-1)
val children = new Array[AnyRef](numchildren)
for (j <- 0 until numchildren)
children (j) = makechild (p.productElement (j))
s (ct) match {
case Some (ti) =>
children (i-1) = makechild (ti)
case None =>
return None
}
val ret = dup (p, children)
Some (ret)
这给出了一些使用限制。 我知道他们正在努力取代这种机制(Issue 2,Issue 31),但我认为听听你们这样做会怎么样有趣呢?
例如,不会复制Positional
var(或任何其他var!)的scala解析器组合器。事实上,一切都不是explict第一个构造函数的一部分(因而也是默认编译器生成的unapply
方法)。
我一直在尝试提供某种特性或类似的东西,我可以添加到我的条件中,dup / childProduct / etc方法可以使用,但没有运气。 (我不知道如何使用案例类copy
)
答案 0 :(得分:3)
我使用Kiama Rewriter
模块的修改版本。它添加了一个Constructable
特征,表示一个值可以deconstruct
本身(使一个数组保持其成分/子元素)和reconstruct
来自一组成分的新实例。当Kiama在其中一个方法Constructable
,dup
,child
或all
中遇到实现some
的值时,它会避免使用反射代码,而是使用{ {1}}和deconstruct
。
除了将客户端代码从可以重写的类型中释放出construct
的要求之外,还允许进行异构重写。换句话说,重写的类型不必与重写的值的具体类型完全相同。
缺点是客户端代码必须定义那些Product
和deconstruct
方法。
(最后并没有与你的问题密切相关,我添加了一个优化,如果转换子值(非原子值)的结果都等于原始值,则避免构建新值。我只添加了这个在处理construct
的分支中。)
答案 1 :(得分:1)
我创建了一个小型GitHub存储库RSchulz/sbtr,其中包含我修改过的Kiama Rewriter.scala
模块。在其中您将找到这些文件:
src/main/scala/rrs/sbtr/SBTR.scala
- 我的“基于策略的术语重写”模块src/main/scala/rrs/sbtr/RewriterFmt.alacs
- 格式化我的样式约定后的原始代码src/main/scala/rrs/sbtr/Rewriter-0.8.alacs
- 稍微更新的0.8版本src/main/scala/rrs/sbtr/Rewriter.alacs
- 我开始的原始版本区分前两个将公开我的修改,这些修改应该可以轻松地反向移植到当前的Kiama Rewriter.scala
代码中。
Rewriter.scala
来源的原始版本和0.8版本之间的主要区别是queryf
的添加,我确实将其延续到SBTR
。 0.8之后的变化尚未纳入。
后缀.alacs
(向后拼写scala)用于防止这些文件被编译。据我所知,构建工具和IDE不能被指示忽略特定文件(至少不容易)。