Skip to content

updates to macro docs #306

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 3 commits into from
Feb 22, 2014
Merged
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions overviews/macros/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ title: Macro Annotations
disqus: true

partof: macros
num: 8
outof: 10
num: 9
outof: 11
languages: [ja]
---
<span class="label important" style="float: right;">MACRO PARADISE</span>
Expand Down
90 changes: 90 additions & 0 deletions overviews/macros/extractors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
layout: overview-large
title: Extractor Macros

disqus: true

partof: macros
num: 6
---
<span class="label warning" style="float: right;">EXPERIMENTAL</span>

**Eugene Burmako**

Extractor macros are shipped with the recent milestone builds of Scala 2.11, starting from 2.11.0-M5, enabled by name-based extractors introduced by Paul Phillips in Scala 2.11.0-M5. Extractor macros are not available in Scala 2.10.x or in macro paradise. Follow the instructions at [http://www.scala-lang.org/download/](http://www.scala-lang.org/download/) to download and use the latest milestone of 2.11.

### The pattern

In a nutshell, given an unapply method (for simplicity, in this
example the scrutinee is of a concrete type, but it's also possible
to have the extractor be polymorphic, as demonstrated in the tests):

def unapply(x: SomeType) = ???

One can write a macro that generates extraction signatures for unapply
on per-call basis, using the target of the calls (`c.prefix`) and the type
of the scrutinee (that comes with `x`), and then communicate these signatures
to the typechecker.

For example, here's how one can define a macro that simply passes
the scrutinee back to the pattern match (for information on how to
express signatures that involve multiple extractees, visit
[scala/scala#2848](https://github.com/scala/scala/pull/2848)).

def unapply(x: SomeType) = macro impl
def impl(c: Context)(x: c.Tree) = {
q"""
new {
class Match(x: SomeType) {
def isEmpty = false
def get = x
}
def unapply(x: SomeType) = new Match(x)
}.unapply($x)
"""
}

In addition to the matcher, which implements domain-specific
matching logic, there's quite a bit of boilerplate here, but
every part of it looks necessary to arrange a non-frustrating dialogue
with the typer. Maybe something better can be done in this department,
but I can't see how, without introducing modifications to the typechecker.

Even though the pattern uses structural types, somehow no reflective calls
are being generated (as verified by `-Xlog-reflective-calls` and then
by manual examination of the produced code). That's a mystery to me, but
that's also good news, since that means that extractor macros aren't
going to induce performance penalties.

Almost. Unfortunately, I couldn't turn matchers into value classes
because one can't declare value classes local. Nevertheless,
I'm leaving a canary in place ([neg/t5903e](https://github.com/scala/scala/blob/00624a39ed84c3fd245dd9df7454d4cec4399e13/test/files/neg/t5903e/Macros_1.scala#L1)) that will let us know
once this restriction is lifted.

### Use cases

In particular, the pattern can be used to implement shapeshifting
pattern matchers for string interpolators without resorting to dirty
tricks. For example, quasiquote unapplications can be unhardcoded now:

def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], ...) = {
...
fun.tpe match {
case ExtractorType(unapply) if mode.inPatternMode =>
// this hardcode in Typers.scala is no longer necessary
if (unapply == QuasiquoteClass_api_unapply) macroExpandUnapply(...)
else doTypedUnapply(tree, fun0, fun, args, mode, pt)
}
}

Rough implementation strategy here would involve writing an extractor
macro that destructures `c.prefix`, analyzes parts of `StringContext` and
then generates an appropriate matcher as outlined above.

Follow our test cases at [run/t5903a](https://github.com/scala/scala/tree/00624a39ed84c3fd245dd9df7454d4cec4399e13/test/files/run/t5903a),
[run/t5903b](https://github.com/scala/scala/tree/00624a39ed84c3fd245dd9df7454d4cec4399e13/test/files/run/t5903b),
[run/t5903c](https://github.com/scala/scala/tree/00624a39ed84c3fd245dd9df7454d4cec4399e13/test/files/run/t5903c),
[run/t5903d](https://github.com/scala/scala/tree/00624a39ed84c3fd245dd9df7454d4cec4399e13/test/files/run/t5903d) to see implementations
of this and other use cases for extractor macros.

Please note that extractor macros must be [whitebox](/overviews/macros/blackbox-whitebox.html), otherwise they will not work.
7 changes: 3 additions & 4 deletions overviews/macros/implicits.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,11 @@ problem is extremely simple and elegant.
In 2.10 we don't allow macro applications to expand until all their type arguments are inferred. However we don't have to do that.
The typechecker can infer as much as it possibly can (e.g. in the running example `C` will be inferred to `Foo` and
`L` will remain uninferred) and then stop. After that we expand the macro and then proceed with type inference using the type of the
expansion to help the typechecker with previously undetermined type arguments.
expansion to help the typechecker with previously undetermined type arguments. This is how it's implemented in Scala 2.11.0.

An illustration of this technique in action can be found in our [files/run/t5923c](https://github.com/scalamacros/kepler/tree/7b890f71ecd0d28c1a1b81b7abfe8e0c11bfeb71/test/files/run/t5923c) tests.
An illustration of this technique in action can be found in our [files/run/t5923c](https://github.com/scala/scala/tree/7b890f71ecd0d28c1a1b81b7abfe8e0c11bfeb71/test/files/run/t5923c) tests.
Note how simple everything is. The `materializeIso` implicit macro just takes its first type argument and uses it to produce an expansion.
We don't need to make sense of the second type argument (which isn't inferred yet), we don't need to interact with type inference -
everything happens automatically.

Please note that there is [a funny caveat](https://github.com/scalamacros/kepler/blob/7b890f71ecd0d28c1a1b81b7abfe8e0c11bfeb71/test/files/run/t5923a/Macros_1.scala)
with Nothings that we plan to address later.
Please note that there is [a funny caveat](https://github.com/scala/scala/blob/7b890f71ecd0d28c1a1b81b7abfe8e0c11bfeb71/test/files/run/t5923a/Macros_1.scala) with Nothings that we plan to address later. Also note that fundep materializers must be [whitebox](/overviews/macros/blackbox-whitebox.html), otherwise they will not work.
6 changes: 4 additions & 2 deletions overviews/macros/paradise.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: Macro Paradise
disqus: true

partof: macros
num: 9
num: 10
languages: [ja]
---
<span class="label success" style="float: right;">NEW</span>
Expand All @@ -15,7 +15,9 @@ languages: [ja]
Macro paradise is a plugin for several versions of Scala compilers.
It is designed to reliably work with production releases of <code>scalac</code>,
making latest macro developments available way before they end up in future versions Scala.
Refer to the roadmap for [the list of supported features and versions](/overviews/macros/roadmap.html).
Refer to the roadmap for [the list of supported features and versions](/overviews/macros/roadmap.html)
and visit [the paradise announcement](http://scalamacros.org/news/2013/08/07/roadmap-for-macro-paradise.html)
to learn more about our support guarantees.

~/210x $ scalac -Xplugin:paradise_*.jar -Xshow-phases
phase name id description
Expand Down
2 changes: 1 addition & 1 deletion overviews/macros/quasiquotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: Quasiquotes
disqus: true

partof: macros
num: 7
num: 8
languages: [ja]
---
<span class="label warning" style="float: right;">EXPERIMENTAL</span>
Expand Down
5 changes: 4 additions & 1 deletion overviews/macros/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ title: Roadmap
disqus: true

partof: macros
num: 10
num: 11
languages: [ja]
---

<span class="label warning" style="float: right;">EXPERIMENTAL</span>

**Eugene Burmako**

Scala team is currently busy with the release of Scala 2.11.0-final, and at the moment we don't have concrete plans for Scala 2.12.
Consequently, roadmaps for Scala 2.12 and Paradise 2.12 don't exist yet. We will update this page once the information becomes available.

| Feature | Scala 2.10 | [Paradise 2.10](/overviews/macros/paradise.html) | [Paradise 2.11](/overviews/macros/paradise.html) | Scala 2.11 |
|-----------------------------------------------------------------------------------|--------------------|------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|-----------------|
| [Blackbox/whitebox separation](/overviews/macros/blackbox-whitebox.html) | No | No <sup>1</sup> | Yes <sup>1</sup> | Yes |
Expand Down
4 changes: 3 additions & 1 deletion overviews/macros/typeproviders.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: Type Providers
disqus: true

partof: macros
num: 6
num: 7
languages: [ja]
---
<span class="label warning" style="float: right;">EXPERIMENTAL</span>
Expand Down Expand Up @@ -84,6 +84,8 @@ it has performance problems caused by the fact that Scala emits reflective calls
of structural types. There are several strategies of dealing with that, but this margin is too narrow to contain them
so I refer you to an amazing blog series by Travis Brown for details: [post 1](http://meta.plasm.us/posts/2013/06/19/macro-supported-dsls-for-schema-bindings/), [post 2](http://meta.plasm.us/posts/2013/07/11/fake-type-providers-part-2/), [post 3](http://meta.plasm.us/posts/2013/07/12/vampire-methods-for-structural-types/).

Please note that fake type providers must be [whitebox](/overviews/macros/blackbox-whitebox.html), otherwise they will not work.

### Real type providers

With the help of [macro paradise](/overviews/macros/paradise.html) and its [macro annotations](/overviews/macros/annotations.html), it becomes
Expand Down