[英]Writing array fill with a macro
I am trying to write a function which fills an array with a given value using scala macros. 我正在尝试使用scala宏编写一个使用给定值填充数组的函数。 For instance a call to:
例如,致电:
val ary = Array( 0, 1, 2 )
fill3( ary, 50+25 )
should be expanded to: 应该扩展到:
val ary = Array(0, 1, 2 )
{
val $value = 50+25
ary(0) = $value
ary(1) = $value
ary(2) = $value
}
Here is my first attempt: 这是我的第一次尝试:
def fill3( ary: Array[Int], x: Int ) = macro fill_impl3
def fill_impl3( c: Context )
( ary: c.Expr[Array[Int]], x: c.Expr[Int]): c.Expr[Unit] = {
import c.universe._
def const(x:Int) = Literal(Constant(x))
//Precompute x
val valName = newTermName("$value")
val valdef = ValDef( Modifiers(), valName, TypeTree(typeOf[Int]), x.tree )
val updates = List.tabulate( 3 ){
i => Apply( Select( ary.tree, "update"), List( const(i), ??? ) )
}
val insts = valdef :: updates
c.Expr[Unit](Block(insts:_*))
}
But here I'm stuck for two reasons: 但在这里,我有两个原因:
$value
) $value
) fill3
, fill4
, fill6
, etc. fill3
和27的数组,我需要几个这样的函数。有没有办法干燥定义,或者我应该写fill3
, fill4
, fill6
等。 Is there the right way to proceed ? 有没有正确的方法继续下去? How can I solve my two problems ?
我怎样才能解决我的两个问题?
EDIT: I realized my initial question was stupid because the size must be known at compile time... 编辑:我意识到我的初始问题是愚蠢的,因为在编译时必须知道大小...
def fill(size:Int, ary: Array[Int], x: Int ) = macro fill_impl
def fill_impl( c: Context )
(size:c.Expr[Int], ary: c.Expr[Array[Int]], x: c.Expr[Int]): c.Expr[Unit] = {
import c.universe._
def const(x:Int) = Literal(Constant(x))
val Literal(Constant(arySize:Int)) = size.tree
//Precompute x
val valName = newTermName("$value")
val valdef = ValDef( Modifiers(), valName, TypeTree(typeOf[Int]), x.tree )
val updates = List.tabulate( arySize ){
i => Apply( Select( ary.tree, "update"), List( const(i), Ident(valName) ) )
}
val insts = valdef :: updates
c.Expr[Unit](Block(insts:_*))
}
You can try to figure it out by using reify
along with printing the raw tree of its result: 您可以尝试通过使用
reify
以及打印其结果的原始树来解决它:
def fill_impl3( c: Context )
( ary: c.Expr[Array[Int]], x: c.Expr[Int]): c.Expr[Unit] = {
import c.universe._
val r = reify {
val $value = x.splice
val $arr = ary.splice
$arr(0) = $value
$arr(1) = $value
$arr(2) = $value
}
println( showRaw( r.tree ))
r
}
Which gives something like 这给了类似的东西
val vt = newTermName("$value")
val at = newTermName("$arr")
val ut = newTermName("update")
Block(List(
ValDef(Modifiers(), vt, TypeTree(), ...),
ValDef(Modifiers(), at, TypeTree(), ...),
Apply(Select(Ident(at), ut), List(Literal(Constant(0)), Ident(vt))),
Apply(Select(Ident(at), ut), List(Literal(Constant(1)), Ident(vt)))),
Apply(Select(Ident(at), ut), List(Literal(Constant(2)), Ident(vt)))
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.