41 votes

Type de retour statique des macros Scala

J'ai donc eu cette macro:

import language.experimental.macros
import scala.reflect.macros.Context

class Foo
class Bar extends Foo { def launchMissiles = "launching" }

object FooExample {
  def foo: Foo = macro foo_impl
  def foo_impl(c: Context): c.Expr[Foo] =
    c.Expr[Foo](c.universe.reify(new Bar).tree)
}

Je l'ai déjà dit trois fois que je veux foo - retour d'un Foo, et pourtant, je peux faire ce qui suit (dans 2.10.0-RC3):

scala> FooExample.foo
res0: Bar = Bar@4118f8dd

scala> res0.launchMissiles
res1: String = launching

La même chose se passe si je retire les paramètres de type ni sur c.Expr. Si je veux vraiment assurez-vous que celui qui appelle, foo ne peut pas voir ce qu'ils obtiennent un Bar, j'ai du ajouter un type de nom dans l'arbre lui-même.

C'est en fait assez grande-cela veut dire par exemple que je peux point une macro à un schéma d'une certaine sorte et créer un anonyme sous-classe de certains Vocabulary classe avec des méthodes membres représentant les termes dans le vocabulaire, et ces derniers seront disponibles sur l'objet retourné.

J'aimerais comprendre exactement ce que je fais, si, si, j'ai un couple de questions. Tout d'abord, qu'est-ce que le type de retour sur l' foo méthode fait pour? Est-il juste disponible (en option) documentation? C'est clairement la limite le type de retour (par exemple, je ne peux pas la changer en Int dans ce cas), et si je le supprimer entièrement, j'obtiens une erreur comme ceci:

scala> FooExample.foo
<console>:8: error: type mismatch;
 found   : Bar
 required: Nothing
              FooExample.foo
                         ^

Mais je peut changer en Any et encore obtenir un statiquement typé Bar quand je l'appelle foo.

Deuxièmement, est-ce le comportement spécifié quelque part? Cela semble assez élémentaire de questions, mais je n'ai pas été en mesure de rechercher une explication claire ou de la discussion.

21voto

Eugene Burmako Points 8453

Ce comportement est underspecified mais, même si cela peut paraître déroutant. Nous avons l'intention de donner des précisions sur le rôle du type de retour en macro signatures, mais pour le moment je me sens comme la flexibilité est une bonne chose.

Parfois, le comportement n'est pas conforme, par exemple, lorsque la macro est pris dans le milieu de l'inférence de type, sa statique signature sera utilisé ( Foo dans votre exemple), pas le type de l'expansion réelle. C'est parce que macro extension est intentionnellement retardé jusqu'à ce que l'inférence de type est faite (de sorte que les macro implémentations obtenez de voir déduit types, pas le type de vars). C'est un compromis, et pas nécessairement le meilleur, de sorte que nous allons la revoir bientôt: https://issues.scala-lang.org/browse/SI-6755.

Un autre problème dans ce département est avec les macros. Lorsque le type de retour d'une fonction implicite de macro est générique et doit être inférée à partir de la demande de type d'une valeur implicite, les mauvaises choses se produisent. Cela rend actuellement impossible d'utiliser des macros pour générer des balises de type: https://issues.scala-lang.org/browse/SI-5923.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X