Open danicheg opened 2 years ago
Yes, that's correct. It's possible to support interpolation of constant values at compile time, but not possible to use non-constant values. Doing so would require changing the macro to return an Either[String, Uri]
when there are one or more non-constant parts and Uri
otherwise. This type switching would require a white box macro in Scala 2 and transparent inline
in Scala 3.
To support interpolation of constant values, we could do something like this:
trait Literally[A]:
type Quotes = scala.quoted.Quotes
type Expr[A] = scala.quoted.Expr[A]
val Expr = scala.quoted.Expr
def validate(s: String)(using Quotes): Either[String, Expr[A]]
def apply(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[String]])(using Quotes): Expr[A] =
apply(strCtxExpr.valueOrAbort.parts, argsExpr.valueOrAbort)
private def apply(parts: Seq[String], args: Seq[String])(using Quotes): Expr[A] =
val str = parts.zipAll(args, "", "").map(t => t(0) + t(1)).mkString("", "", "")
validate(str) match
case Left(err) =>
quotes.reflect.report.error(err)
???
case Right(a) =>
a
Usage:
scala> inline val x = "4"
scala> val y = port"1${x}2"
val y: org.typelevel.literally.examples.Port = Port(142)
This is too limited though as it requires the args list to be strings. It would be nicer to support arbitrary types there. Overall, I don't think the complexity is worth it.
This issue is a follow-up from https://github.com/http4s/http4s/issues/3433. I've struggled with this a bit and think it's quite problematic to embed string interpolations to
uri""
andpath""
ofhttp4s
(actually, it's so for every interpolated macros based onliterally
):validate
is calling at compile time).means that we should check the value of
foo
at the runtime (generally,foo
could be some computation, not a constant value). So bringing embedded string interpolations means we should proceed with runtime values at compile time (because of 1). I'm not that much a Scala macros astronaut, but am feeling it's probably impossible.UPD: speaking more accurately, compile-time checking is only possible for the literal part of the passed string.
If anyone has insights about that, please share them here.