quasiquotes
Below you can find a comprehensive map between Scala's language constructs and various quasiquotes in scala.meta. If something's missing here, it's a bug that should be submitted to our issue tracker.
This specification describes quasiquote syntax using a markedly condensed notation. If you have troubles decyphering it, consult the "Legend" section in the end of the document.
Expressions (meta.Term)
| Quasiquote | |
|---|---|
| Literal | q"<literal>" |
| This | q"this", q"$name.this" |
| Super | q"super", q"$name.super", q"super[$name]", q"$name.super[$name]" |
| Name | q"<name>" when interpolation is not needed, otherwise Term.Name(name) |
| Selection | q"$expr.$ename" |
| Interpolation | Not supported yet |
| Application | q"$expr(...$exprss)" |
| Type Application | q"$expr[..$tpesnel]" |
| Infix Application | q"$expr $ename[..$tpes] $expr", q"$expr $ename[..$tpes] (..$exprs)" |
| Unary Application | q"!$expr", q"~$expr", q"-$expr", "+$expr" |
| Assign | q"$expr = $expr" |
| Return | q"return $expr" |
| Throw | q"throw $expr" |
| Ascribe | q"$expr: $tpe" |
| Annotate | q"$expr: ..@$annotsnel" |
| Tuple | q"(..$exprsnel)" |
| Block | q"{ ..$stats }" |
| If | q"if ($expr) $expr else $expr" |
| Match | q"$expr match { ..case $casesnel }" |
| Try | q"try $expr catch { ..case $cases } finally $expropt" |
| Try With Handler | q"try $expr catch $expr finally $expropt" |
| Function | q"(..$params) => $expr" |
| Partial Function | q"{ ..case $casesnel }" |
| While | q"while ($expr) $expr" |
| Do While | q"do $expr while($expr)" |
| For | q"for (..$enumeratorsnel) $expr" |
| For Yield | q"for (..$enumeratorsnel) yield $expr" |
| New | q"new $init" |
| New Anonymous | q"new { ..$stat } with ..$inits { $self => ..$stats }" |
| Placeholder | q"_" |
| Eta Expansion | q"$expr _" |
| Repeated | q"$expr: _*" |
Types (meta.Type)
| Quasiquote | |
|---|---|
| Literal | t"<literal>" |
| Name | t"<name>" when interpolation is not needed, otherwise Type.Name(name) |
| Selection | t"$eref.$tname" |
| Projection | t"$tpe#$tname" |
| Singleton | t"$eref.type" |
| Application | t"$tpe[..$tpesnel] |
| Infix Application | t"$tpe $tname $tpe" |
| With | t"$tpe with $tpe" (only for supported dialects) |
| And | t"$tpe & $tpe" (only for supported dialects) |
| Or | t"$tpe | $tpe" (only for supported dialects) |
| Function | t"(..$tpes) => $tpe" |
| Implicit Function | t"implicit (..$tpes) => $tpe" |
| Tuple | t"(..$tpesnel)" |
| Refine | t"$tpeopt { ..$stats }" |
| Existential | t"$tpe forSome { ..$statsnel }" |
| Annotate | t"$tpe ..@$annotsnel" |
| Lambda | t[..$tparams] => $tpe |
| Method | t(...$paramss): $tpe |
| Placeholder | t"_ >: $tpeopt <: $tpeopt" |
| By Name | t"=> $tpe" |
| Repeated | t"$tpe*" |
| Var | Not supported |
Patterns (meta.Pat) and Cases (meta.Case)
| Quasiquote | |
|---|---|
| Literal | p"<lit>" |
| Wildcard | p"_" |
| Sequence Wildcard | p"_*" |
| Var | p"<name>" |
| Bind | p"$pat @ $pat" |
| Alternative | p"$pat | $pat" |
| Tuple | p"(..$patsnel)" |
| Extract | p"$expr(..$pats)" |
| Infix Extract | p"$pat $ename (..$pats)" |
| Interpolation | Not supported yet |
| Typed | p"$pat: $tpe" |
| Name | p"`<name>`" |
| Selection | p"$expr.$ename" |
| Case | p"case $pat if $expropt => $expr" |
Members (meta.Member)
Declarations
| Quasiquote | |
|---|---|
| Val | q"..$mods val ..$patsnel: $tpe" |
| Var | q"..$mods var ..$patsnel: $tpe" |
| Def | q"..$mods def $ename[..$tparams](...$paramss): $tpe" |
| Type | q"..$mods type $tname[..$tparams] >: $tpeopt <: $tpeopt" |
Definitions
| Quasiquote | |
|---|---|
| Val | q"..$mods val ..$patsnel: $tpeopt = $expr" |
| Var | q"..$mods var ..$patsnel: $tpeopt = $expropt" |
| Def | q"..$mods def $ename[..$tparams](...$paramss): $tpeopt = $expr" |
| Macro | q"..$mods def $ename[..$tparams](...$paramss): $tpeopt = macro $expr" |
| Type | q"..$mods type $tname[..$tparams] = $tpe" |
| Class | q"..$mods class $tname[..$tparams] ..$ctorMods (...$paramss) $template" |
| Trait | q"..$mods trait $tname[..$tparams] $template" |
| Object | q"..$mods object $ename $template" |
| Package Object | q"package object $ename $template" |
| Package | q"package $eref { ..$stats }" |
| Primary Ctor | q"..$mods def this(...$paramss)" |
| Secondary Ctor | q"..$mods def this(...$paramss) = $expr" |
$templateabove can be replaced with eitherextendsfollowed by the full signature fromTemplate, or just{ $self => ..$stats }if no parents are expected.
Value Parameters (meta.Term.Param)
| Quasiquote | |
|---|---|
| Term Param | param"..$mods $name: $tpeopt = $expropt" |
Type Parameters (meta.Type.Param)
| Quasiquote | |
|---|---|
| Type Param | tparam"..$mods $name[..$tparams] >: $tpeopt <: $tpeopt <% ..$tpes : ..$tpes" |
Inits (meta.Init)
| Quasiquote | |
|---|---|
| Init | init"$tpe(...$exprss)", init"this(...$exprss)" |
Selfs (meta.Self)
| Quasiquote | |
|---|---|
| Self | self"$name: $tpeopt", self"this: $tpeopt" |
Template (meta.Template)
| Quasiquote | |
|---|---|
| Template | template"{ ..$stats } with ..$inits { $self => ..$stats }" (first stats is early initializers, second stats is regular statements in the body of the template). |
Modifiers (meta.Mod)
| Quasiquote | |
|---|---|
| Annotation | mod"@$annot" |
| Private | mod"private[$ref]" |
| Protected | mod"protected[$ref]" |
| Implicit | mod"implicit" |
| Final | mod"final" |
| Sealed | mod"sealed" |
| Override | mod"override" |
| Case | mod"case" |
| Abstract | mod"abstract" |
| Covariant | mod"+" |
| Contravariant | mod"-" |
| Lazy | mod"lazy" |
| Val Param | mod"valparam" |
| Var Param | mod"varparam" |
| Inline | mod"inline" |
Enumerators (meta.Enum)
| Quasiquote | |
|---|---|
| Generator | enumerator"$pat <- $expr" |
| Value | enumerator"$pat = $expr" |
| Guard | enumerator"if $expr" |
Imports (meta.Import)
| Quasiquote | |
|---|---|
| Import | q"import ..$importersnel" |
Importer (meta.Importer)
| Quasiquote | |
|---|---|
| Importer | importer"$eref.{..$importeesnel}" |
Importees (meta.Importee)
| Quasiquote | |
|---|---|
| Name | importee"$name" |
| Rename | importee"$name => $name" |
| Unimport | importee"$name => _" |
| Wildcard | importee"_" |
Sources (meta.Source)
| Quasiquote | |
|---|---|
| Source | source"..$stats" |
Legend
The tables above define quasiquote syntax using a notation called quasiquote templates. A quasiquote is valid if it conforms to exactly one quasiquote template according to the following rules:
-
Any trivia token (e.g. whitespace and comments) in a quasiquote template or a quasiquote is insignificant and is ignored for the purposes of conformance testing.
-
Any non-trivia token in a quasiquote template, except for an unquote template, means that exactly that token is required in a quasiquote, with the following exceptions:
- Parentheses, brackets and braces around unquotes are oftentimes dropped if
they wrap empty lists, e.g.
q"x + y"conforms toq"$expr $ename[..$tpes] $expr". withis dropped if there are zero or one inits, e.g. bothq"new {}"andq"new C"conform toq"new { ..$stat } with ..$inits { $self => ..$stats }.- This list is probably incomplete. Please submit an issue if you find any discrepancies.
- Parentheses, brackets and braces around unquotes are oftentimes dropped if
they wrap empty lists, e.g.
-
An unquote template (
$smth,..$smthor...$smth) works as follows:-
First, we strip standard suffixes from
smthusing the "Suffixes" table (e.g.exprssnelmeans a non-empty list of lists ofexpr). -
Second, we figure out the expected type of
smthusing the "Shorthands" table (e.g.exprmeansTerm, soexprssnelmeansList[List[Term]]). -
Third, we apply an appropriate number of replications to the unquote template to have it match the corresponding part of a quasiquote that's being tested for conformance:
$smthcan not be replicated...$smthmeans an arbitrary mix of$smthand..$smthunquote templates separated according to their location (e.g. an empty string,[$tpe],[..$tpes, $tpe]all conform to[..$tpes], and the separator is a comma, as appropriate for a list of type arguments)....$smthmeans an arbitrary mix of$smth,..$smthand...$smthunquote templates, separated according to their location (e.g. an empty string,(...$exprss),(..$exprs)($expr1, $expr2)()all conform to(...$exprss), and the separator are matching parentheses, as appropriate for a list of arguments).- If a suffix of
smthsays that it's a non-empty list, then replication can't result in an empty list. - If a quasiquote is used as a pattern, then some replications may be illegal.
-
Finally, we match the unquotes after replication against the corresponding parts of the quasiquote under conformance test. There are three possibilities for a match: scala syntax, unquote, lifted unquote.
-
-
If not specified explicitly, quasiquote templates work for both construction and deconstruction. In some cases, a template is only applicable to construction (e.g. it's impossible to pattern match a name without specifying an expected type explicitly, because patterns like in
term match { case q"$ename" => }will match any term, not limited to just term names).
Shorthands
| Type | Shorthand |
|---|---|
| meta.Case | $case |
| meta.Enumerator | $enumerator |
| meta.Mod | $mod |
| meta.Mod.Annot | $annot |
| meta.Name | $name |
| meta.Importee | $importee |
| meta.Importer | $importer |
| meta.Init | $init |
| meta.Pat | $pat |
| meta.Ref | $ref |
| meta.Self | $self |
| meta.Stat | $stat |
| meta.Template | $template |
| meta.Term | $expr |
| meta.Term.Name | $ename |
| meta.Term.Ref | $eref |
| meta.Term.Param | $param |
| meta.Type | $tpe |
| meta.Type.Name | $tname |
| meta.Type.Param | $tparam |
Suffixes
| Suffix | Wrapped Type | Example |
|---|---|---|
| -s | List[_] | exprs: List[meta.Term] |
| -ss | List[List[_]] | exprss: List[List[meta.Term]] |
| -opt | Option[_] | expropt: Option[meta.Term] |
| -nel | _ | tpesnel: List[meta.Type] |
Comments
Starting with v4.14.3, scalameta supports comments attached to trees. Specifically for quasiquotes, the only special case is with interpolated comments which must be passed as scala strings (since each interpolated value is parsed as valid scala):
val scaladoc = q"""
"some scaladoc string"
"""
val comment = q"\"some comment string\""
val tree = q"""
/** $scaladoc */
val foo = bar // $comment
"""