You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/docs/reference/metaprogramming/macros.md
+56-15Lines changed: 56 additions & 15 deletions
Original file line number
Diff line number
Diff line change
@@ -78,21 +78,23 @@ ${'[T]} = T
78
78
The type signatures of quotes and splices can be described using
79
79
two fundamental types:
80
80
81
-
-`Expr[T]`: abstract syntax trees representing expressions of type `T`
82
-
-`Type[T]`: type structures representing type `T`.
81
+
-`Expr[T]`: abstract syntax trees representing expressions of type `T`
82
+
-`Type[T]`: type structures representing type `T`.
83
83
84
84
Quoting takes expressions of type `T` to expressions of type `Expr[T]`
85
85
and it takes types `T` to expressions of type `Type[T]`. Splicing
86
86
takes expressions of type `Expr[T]` to expressions of type `T` and it
87
87
takes expressions of type `Type[T]` to types `T`.
88
88
89
89
The two types can be defined in package `scala.quoted` as follows:
90
+
90
91
```scala
91
92
packagescala.quoted
92
93
93
94
sealedabstractclassExpr[+T]
94
95
sealedabstractclassType[T]
95
96
```
97
+
96
98
Both `Expr` and `Type` are abstract and sealed, so all constructors for
97
99
these types are provided by the system. One way to construct values of
98
100
these types is by quoting, the other is by type-specific lifting
@@ -103,7 +105,7 @@ operations that will be discussed later on.
103
105
A fundamental *phase consistency principle* (PCP) regulates accesses
104
106
to free variables in quoted and spliced code:
105
107
106
-
-_For any free variable reference `x`, the number of quoted scopes and the number of spliced scopes between the reference to `x` and the definition of `x` must be equal_.
108
+
-_For any free variable reference `x`, the number of quoted scopes and the number of spliced scopes between the reference to `x` and the definition of `x` must be equal_.
107
109
108
110
Here, `this`-references count as free variables. On the other
109
111
hand, we assume that all imports are fully expanded and that `_root_` is
@@ -129,8 +131,8 @@ situations described above.
129
131
130
132
In what concerns the range of features it covers, this form of macros introduces
131
133
a principled metaprogramming framework that is quite close to the MetaML family of
132
-
languages. One difference is that MetaML does not have an equivalent of the PCP
133
-
-quoted code in MetaML _can_ access variables in its immediately enclosing
134
+
languages. One difference is that MetaML does not have an equivalent of the PCP -
135
+
quoted code in MetaML _can_ access variables in its immediately enclosing
134
136
environment, with some restrictions and caveats since such accesses involve
135
137
serialization. However, this does not constitute a fundamental gain in
@@ -482,6 +517,7 @@ that invokation of `run` in splices. Consider the following expression:
482
517
```scala
483
518
'{ (x: Int) =>${ run('x); 1 } }
484
519
```
520
+
485
521
This is again phase correct, but will lead us into trouble. Indeed, evaluating
486
522
the splice will reduce the expression `run('x)` to `x`. But then the result
487
523
@@ -566,6 +602,7 @@ sum
566
602
```
567
603
568
604
Finally cleanups and dead code elimination:
605
+
569
606
```scala
570
607
valarr:Array[Int] =Array.apply(1, [2,3:Int]:Int*)
571
608
varsum=0
@@ -632,12 +669,12 @@ It is possible to deconstruct or extract values out of `Expr` using pattern matc
632
669
633
670
`scala.quoted` contains objects that can help extracting values from `Expr`.
634
671
635
-
*`scala.quoted.Expr`/`scala.quoted.Exprs`: matches an expression of a value (or list of values) and returns the value (or list of values).
636
-
*`scala.quoted.Const`/`scala.quoted.Consts`: Same as `Expr`/`Exprs` but only works on primitive values.
637
-
*`scala.quoted.Varargs`: matches an explicit sequence of expressions and returns them. These sequences are useful to get individual `Expr[T]` out of a varargs expression of type `Expr[Seq[T]]`.
638
-
672
+
-`scala.quoted.Expr`/`scala.quoted.Exprs`: matches an expression of a value (or list of values) and returns the value (or list of values).
673
+
-`scala.quoted.Const`/`scala.quoted.Consts`: Same as `Expr`/`Exprs` but only works on primitive values.
674
+
-`scala.quoted.Varargs`: matches an explicit sequence of expressions and returns them. These sequences are useful to get individual `Expr[T]` out of a varargs expression of type `Expr[Seq[T]]`.
639
675
640
676
These could be used in the following way to optimize any call to `sum` that has statically known values.
caseNone=> report.error(s"could not find implicit for ${showTp.show}", arg); '{???}
758
+
caseNone=> report.error(s"could not find implicit for ${Type.show[Show[tp]]}", arg); '{???}
720
759
}
721
760
}
722
761
valnewArgsExpr=Varargs(argShowedExprs)
@@ -746,9 +785,11 @@ then the rest of the quote can refer to this definition.
746
785
```
747
786
748
787
To match such a term we need to match the definition and the rest of the code, but we need to explicitly state that the rest of the code may refer to this definition.
788
+
749
789
```scala
750
790
case'{ valy:Int= $x; $body(y):Int } =>
751
791
```
792
+
752
793
Here `$x` will match any closed expression while `$body(y)` will match an expression that is closed under `y`. Then
753
794
the subexpression of type `Expr[Int]` is bound to `body` as an `Expr[Int => Int]`. The extra argument represents the references to `y`. Usually this expression is used in combination with `Expr.betaReduce` to replace the extra argument.
0 commit comments