I am trying to write a function which fills an array with a given value using scala macros. 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:
- I don't know hot to get the precomputed value (
$value) - I need several of these function for Arrays of size 3, 4, 6, 9 and 27. Is there a way to dry the definitions, or should I write
fill3,fill4,fill6, etc.
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...