Metaprogramming: variable number of parameters

Is it possible to write Scala code that generates a quote of a def with a number of parameters dynamically specified at runtime?

For example, for a fixed number of parameters, I can write Scala code that generates the corresponding quoted sum def:

import scala.quoted.{Expr, Quotes}

// Returns a quoted def of sum2.
def sum2DefQuote(using Quotes): Expr[Unit] = '{
  def sum2(a1: Int, a2: Int): Int = a1 + a2
}
// Returns a quoted def of sum3.
def sum3DefQuote(using Quotes): Expr[Unit] = '{
  def sum3(a1: Int, a2: Int, a3: Int): Int = a1 + a2 + a3
}

Can the code be generalized to take the number of parameters as an argument?

// Is it possible to write such a function in Scala?
def sumNDefQuote(n: Int)(using Quotes): Expr[Unit] =
  assert(n >= 0)
  ??? // How to generate the parameter list dynamically?

Do you need the arguments to be individually listed, with number of parameters as argument, or would you be OK with using a Seq:

scala> def f(xs: Int*): Int = xs.sum
def f(xs: Int*): Int

scala> f(1, 2, 3, 4)
val res0: Int = 10
1 Like

I would like them to be individually listed.

I want to know whether Scala metaprogramming is complete, in the sense that any computable function returning a quoted.Expr is expressible in Scala.

If sumNDefQuote is not expressible in Scala, then its metaprogramming is not complete in that sense.

I think this is only possible via reflection. You can use variable arguments in quotes though. See Quoted Code | Macros in Scala 3 | Scala Documentation and look for Varargs. You have a ToExpr[StringContext] example.

1 Like

Thanks! I had a look at Scala 3 “reflection”. It looks like a lower-level (and less type-safe?) way of doing metaprogramming, and it might well be possible to code sumNDefQuote with it.

Unfortunately, I was unable to find good documentation, so figuring out how to use it looks like a major endeavor.

You don’t have to stick to one or the other. You can “mix and match” as per your needs.

As for documentation, its pretty detailed, so you have to work through it and experiment quite a bit. Try also looking at this article (someone may suggest others) that may help you:

1 Like