@@ -7,10 +7,9 @@ title: "Macros"
7
7
8
8
## Macros: Quotes and Splices
9
9
10
- Macros are built on two well-known fundamental operations: quotation and
11
- splicing. Quotation is expressed as ` '{...} ` for expressions and as ` '[...] `
12
- for types. Splicing is expressed as ` ${ ... } ` . Additionally, within a quote
13
- or a splice we can quote or splice identifiers directly (i.e. ` 'e ` and ` $e ` ).
10
+ Macros are built on two well-known fundamental operations: quotation and splicing.
11
+ Quotation is expressed as ` '{...} ` for expressions and splicing is expressed as ` ${ ... } ` .
12
+ Additionally, within a quote or a splice we can quote or splice identifiers directly (i.e. ` 'e ` and ` $e ` ).
14
13
Readers may notice the resemblance of the two aforementioned syntactic
15
14
schemes with the familiar string interpolation syntax.
16
15
@@ -45,7 +44,7 @@ def showExpr(expr: Expr[Boolean])(using Quotes): Expr[String] =
45
44
```
46
45
47
46
If ` e ` is an expression, then ` '{e} ` represents the typed
48
- abstract syntax tree representing ` e ` . If ` T ` is a type, then ` ' [T]`
47
+ abstract syntax tree representing ` e ` . If ` T ` is a type, then ` Type.of [T]`
49
48
represents the type structure representing ` T ` . The precise
50
49
definitions of "typed abstract syntax tree" or "type-structure" do not
51
50
matter for now, the terms are used only to give some
@@ -62,14 +61,12 @@ Quotes and splices can also be applied directly to identifiers. An identifier
62
61
splice ` ${x} ` . Analogously, an quoted identifier ` 'x ` that appears inside a splice
63
62
is treated as a quote ` '{x} ` . See the Syntax section below for details.
64
63
65
- Quotes and splices are duals of each other. For arbitrary
66
- expressions ` e ` and types ` T ` we have:
64
+ Quotes and splices are duals of each other.
65
+ For arbitrary expressions ` e ` we have:
67
66
68
67
``` scala
69
68
$ {' {e}} = e
70
69
' {$ {e}} = e
71
- $ {' [T ]} = T
72
- ' [$ {T }] = T
73
70
```
74
71
75
72
## Types for Quotations
@@ -78,7 +75,7 @@ The type signatures of quotes and splices can be described using
78
75
two fundamental types:
79
76
80
77
- ` Expr[T] ` : abstract syntax trees representing expressions of type ` T `
81
- - ` Type[T] ` : type structures representing type ` T ` .
78
+ - ` Type[T] ` : non erased representation of type ` T ` .
82
79
83
80
Quoting takes expressions of type ` T ` to expressions of type ` Expr[T] `
84
81
and it takes types ` T ` to expressions of type ` Type[T] ` . Splicing
@@ -90,8 +87,8 @@ The two types can be defined in package [`scala.quoted`](https://dotty.epfl.ch/a
90
87
``` scala
91
88
package scala .quoted
92
89
93
- sealed abstract class Expr [+ T ]
94
- sealed abstract class Type [T ]
90
+ sealed trait Expr [+ T ]
91
+ sealed trait Type [T ]
95
92
```
96
93
97
94
Both ` Expr ` and ` Type ` are abstract and sealed, so all constructors for
@@ -375,7 +372,7 @@ where `T` is not defined in the current stage, we construct the type constructor
375
372
of ` List ` applied to the splice of the result of searching for a given instance for ` Type[T] ` :
376
373
377
374
``` scala
378
- ' [ List [ $ { summon[Type [T ]] } ] ]
375
+ Type .of [ List [ summon[Type [T ]]. Underlying ] ]
379
376
```
380
377
381
378
This is exactly the algorithm that Scala 2 uses to search for type tags.
@@ -493,7 +490,7 @@ var x: Expr[T] = ...
493
490
This code, if it was accepted, would _ extrude_ a reference to a quoted variable
494
491
` y ` from its scope. This would subsequently allow access to a variable outside the
495
492
scope where it is defined, which is likely problematic. The code is clearly
496
- phase consistent, so we cannot use PCP to rule it out. Instead we postulate a
493
+ phase consistent, so we cannot use PCP to rule it out. Instead, we postulate a
497
494
future effect system that can guarantee that splices are pure. In the absence of
498
495
such a system we simply demand that spliced expressions are pure by convention,
499
496
and allow for undefined compiler behavior if they are not. This is analogous to
@@ -502,7 +499,7 @@ verified, to be pure.
502
499
503
500
[ Multi-Stage Programming] ( ./staging.md ) introduces one additional method where
504
501
you can expand code at runtime with a method ` run ` . There is also a problem with
505
- that invokation of ` run ` in splices. Consider the following expression:
502
+ that invocation of ` run ` in splices. Consider the following expression:
506
503
507
504
``` scala
508
505
' { (x : Int ) => $ { run(' x ); 1 } }
@@ -573,7 +570,7 @@ val arr: Array[Int] = Array.apply(1, [2,3 : Int]:Int*)
573
570
574
571
var sum = 0
575
572
val f = x => ' {sum += $x}
576
- $ { _root_.Macros .map(' arr , ' f )(' [Int ])}
573
+ $ { _root_.Macros .map(' arr , ' f )(Type .of [Int ])}
577
574
sum
578
575
```
579
576
@@ -720,7 +717,7 @@ private def sumExpr(args1: Seq[Expr[Int]])(using Quotes): Expr[Int] =
720
717
721
718
### Recovering precise types using patterns
722
719
723
- Sometimes it is necessary to get a more precise type for an expression. This can be achived using the following pattern match.
720
+ Sometimes it is necessary to get a more precise type for an expression. This can be achieved using the following pattern match.
724
721
725
722
``` scala
726
723
def f (expr : Expr [Any ])(using Quotes ) = expr match
0 commit comments