2013-08-28 9 views
11

Ho la seguente macro definisce una classe e il ritorno un'istanza di quella classe (con Scala 2.10.2 e il plugin macro):metodo non può essere letta in classe generata Macro

def test[T] = macro testImpl[T] 

def testImpl[T : c.WeakTypeTag](c: Context): c.Expr[Any] = { 
    import c.universe._ 
    val className = newTypeName("Test") 

    c.Expr { q""" 
    class $className { 
     def method = 1 
    } 
    new $className 
    """} 
} 

Quando chiamo la macro :

case class Cat(name: String) 

val t = test[Cat].method 

ottengo il seguente errore:

method method in class Test cannot be accessed in Test 
val t = test[Cat].method 
       ^

il mio obiettivo generale è quello di utilizzare vampire methods e usare le virgolette per descrivere la classe generata. Come posso risolvere questo errore?

+0

La tua classe sintetizzata non può estendere un tratto che definisce "metodo" in modo astratto? –

+0

No perché ho bisogno di generare quei metodi con nomi specifici. E nel tentativo di farlo mi sono reso conto che non potevo nemmeno accedere ai metodi non generati. Sospetto che non sto usando le virgolette in modo corretto qui. – Eric

+0

Non avevo idea che ora esistesse un plug-in per il compilatore per macro paradise (al contrario di essere costretto a usare un compilatore a forcella). Se solo per l'apprendimento, grazie mille per la tua domanda. –

risposta

10

Nel mio post sui metodi vampiri menziono this workaround per this bug. Per qualche motivo al momento non è possibile visualizzare i metodi di una classe anonima sull'istanza restituita dalla macro, a meno che non si crei una classe wrapper che estenda la classe con i metodi e restituisca invece un'istanza di tale.

Stai vedendo lo stesso bug da un'angolazione leggermente diversa. Hai chiamato la classe con i metodi che vuoi vedere sul tipo strutturale dell'istanza restituita, ma hai ancora bisogno di un wrapper. Quanto segue funziona:

c.Expr { q""" 
    class $className { 
     def method = 1 
    } 
    new $className {} 
    """} 

Nota che tutto quello che ho fatto è aggiungere una coppia di parentesi alla linea creare l'istanza, in modo che ricevo un'istanza di una classe anonima che si estende $className invece di un $className.

Non ho idea di cosa ci sia dietro a questo bug e non sono sicuro che Eugene ne sappia di più. Di recente ho confermato che è ancora disponibile nell'ultima build di 2.11.

+1

Lo porterò alla prossima riunione di riflessione. –

+1

Sapevo che avresti fatto un passo avanti a Travis. Grazie! Ora posso preparare la prossima domanda :-) – Eric

+1

Sembra che sia di progettazione. Secondo Martin, consentire ai membri immediati delle classi locali di finire in tipi strutturali ha portato ad alcuni problemi strani allora, ecco perché ora bisogna fare uno sforzo in più per esporre questi membri. –

Problemi correlati