Skip to content

Instantly share code, notes, and snippets.

@halotukozak
Created January 9, 2026 20:56
Show Gist options
  • Select an option

  • Save halotukozak/a5e439309b3c2d010d93f38d9fd3eec7 to your computer and use it in GitHub Desktop.

Select an option

Save halotukozak/a5e439309b3c2d010d93f38d9fd3eec7 to your computer and use it in GitHub Desktop.
import scala.NamedTuple.{AnyNamedTuple, NamedTuple}
import scala.quoted.*
transparent inline def defaults[T](inline fun: T): DefaultsExtractor = ${ defaultsImpl('{ fun }) }
def defaultsImpl[T: Type](expr: Expr[T])(using quotes: Quotes): Expr[DefaultsExtractor] =
import quotes.reflect.*
val Lambda(_, Apply(term, _)) = expr.asTerm.underlying.runtimeChecked
val methodSymbol = term.symbol
val prefix = methodSymbol.name + "$default$"
val paramNames = methodSymbol.paramSymss.flatten.map(_.name).toVector
val defaults = methodSymbol.owner.methodMembers
.collect:
case m if m.name.startsWith(prefix) =>
paramNames(m.name.stripPrefix(prefix).toInt - 1) -> Ref(m)
val defaultsExpr =
val list = Expr.ofSeq:
defaults.map: (name, term) =>
Expr.ofTuple((Expr(name), term.asExpr))
'{ $list.toMap }
val fieldsType = TypeRepr
.of[NamedTuple]
.appliedTo:
defaults
.foldLeft((TypeRepr.of[EmptyTuple], TypeRepr.of[EmptyTuple])):
case ((names, types), (name, term)) =>
(
TypeRepr.of[*:].appliedTo(List(ConstantType(StringConstant(name)), names)),
TypeRepr.of[*:].appliedTo(List(term.tpe, types)),
)
.toList
fieldsType.asType match
case '[ type fields <: AnyNamedTuple; fields ] =>
'{
new DefaultsExtractor($defaultsExpr):
type Fields = fields
}
sealed class DefaultsExtractor(defaults: Map[String, Any]) extends Selectable:
type Fields <: AnyNamedTuple
final def selectDynamic(name: String): Any = defaults(name)
@main
def main(): Unit =
assert(defaults(method).x == 10)
assert(defaults(method).y == "two")
def method(x: Int = 10, y: String = "two") = ???
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment