Skip to content

Update macros.md #11903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 27, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 14 additions & 17 deletions docs/docs/reference/metaprogramming/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ title: "Macros"

## Macros: Quotes and Splices

Macros are built on two well-known fundamental operations: quotation and
splicing. Quotation is expressed as `'{...}` for expressions and as `'[...]`
for types. Splicing is expressed as `${ ... }`. Additionally, within a quote
or a splice we can quote or splice identifiers directly (i.e. `'e` and `$e`).
Macros are built on two well-known fundamental operations: quotation and splicing.
Quotation is expressed as `'{...}` for expressions and splicing is expressed as `${ ... }`.
Additionally, within a quote or a splice we can quote or splice identifiers directly (i.e. `'e` and `$e`).
Readers may notice the resemblance of the two aforementioned syntactic
schemes with the familiar string interpolation syntax.

Expand Down Expand Up @@ -45,7 +44,7 @@ def showExpr(expr: Expr[Boolean])(using Quotes): Expr[String] =
```

If `e` is an expression, then `'{e}` represents the typed
abstract syntax tree representing `e`. If `T` is a type, then `'[T]`
abstract syntax tree representing `e`. If `T` is a type, then `Type.of[T]`
represents the type structure representing `T`. The precise
definitions of "typed abstract syntax tree" or "type-structure" do not
matter for now, the terms are used only to give some
Expand All @@ -62,14 +61,12 @@ Quotes and splices can also be applied directly to identifiers. An identifier
splice `${x}`. Analogously, an quoted identifier `'x` that appears inside a splice
is treated as a quote `'{x}`. See the Syntax section below for details.

Quotes and splices are duals of each other. For arbitrary
expressions `e` and types `T` we have:
Quotes and splices are duals of each other.
For arbitrary expressions `e` we have:

```scala
${'{e}} = e
'{${e}} = e
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this now actually true? At some point, some normalization was observable .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was in the patterns, not here.

${'[T]} = T
'[${T}] = T
```

## Types for Quotations
Expand All @@ -78,7 +75,7 @@ The type signatures of quotes and splices can be described using
two fundamental types:

- `Expr[T]`: abstract syntax trees representing expressions of type `T`
- `Type[T]`: type structures representing type `T`.
- `Type[T]`: non erased representation of type `T`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above in line 48 you say "type structure"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there is much more to improve in this document. Might need a full rewrite.


Quoting takes expressions of type `T` to expressions of type `Expr[T]`
and it takes types `T` to expressions of type `Type[T]`. Splicing
Expand All @@ -90,8 +87,8 @@ The two types can be defined in package [`scala.quoted`](https://dotty.epfl.ch/a
```scala
package scala.quoted

sealed abstract class Expr[+T]
sealed abstract class Type[T]
sealed trait Expr[+T]
sealed trait Type[T]
```

Both `Expr` and `Type` are abstract and sealed, so all constructors for
Expand Down Expand Up @@ -375,7 +372,7 @@ where `T` is not defined in the current stage, we construct the type constructor
of `List` applied to the splice of the result of searching for a given instance for `Type[T]`:

```scala
'[ List[ ${ summon[Type[T]] } ] ]
Type.of[ List[ summon[Type[T]].Underlying ] ]
```

This is exactly the algorithm that Scala 2 uses to search for type tags.
Expand Down Expand Up @@ -493,7 +490,7 @@ var x: Expr[T] = ...
This code, if it was accepted, would _extrude_ a reference to a quoted variable
`y` from its scope. This would subsequently allow access to a variable outside the
scope where it is defined, which is likely problematic. The code is clearly
phase consistent, so we cannot use PCP to rule it out. Instead we postulate a
phase consistent, so we cannot use PCP to rule it out. Instead, we postulate a
future effect system that can guarantee that splices are pure. In the absence of
such a system we simply demand that spliced expressions are pure by convention,
and allow for undefined compiler behavior if they are not. This is analogous to
Expand All @@ -502,7 +499,7 @@ verified, to be pure.

[Multi-Stage Programming](./staging.md) introduces one additional method where
you can expand code at runtime with a method `run`. There is also a problem with
that invokation of `run` in splices. Consider the following expression:
that invocation of `run` in splices. Consider the following expression:

```scala
'{ (x: Int) => ${ run('x); 1 } }
Expand Down Expand Up @@ -573,7 +570,7 @@ val arr: Array[Int] = Array.apply(1, [2,3 : Int]:Int*)

var sum = 0
val f = x => '{sum += $x}
${ _root_.Macros.map('arr, 'f)('[Int])}
${ _root_.Macros.map('arr, 'f)(Type.of[Int])}
sum
```

Expand Down Expand Up @@ -720,7 +717,7 @@ private def sumExpr(args1: Seq[Expr[Int]])(using Quotes): Expr[Int] =

### Recovering precise types using patterns

Sometimes it is necessary to get a more precise type for an expression. This can be achived using the following pattern match.
Sometimes it is necessary to get a more precise type for an expression. This can be achieved using the following pattern match.

```scala
def f(expr: Expr[Any])(using Quotes) = expr match
Expand Down