2015-05-20 9 views
7

Sono nuovo di scala macro e ho trascorso un paio di giorni cercando di scrivere il mio primissimo. Ho un problema con la concatenazione di quasiquotes.Scala quasiquote concatenazione

C'è un elenco di clausole case, diciamo il seguente:

val cases = cq"x => 1 " :: cq"_ => 0 " :: Nil 

e ho bisogno di costruire un funzione parziale da esso. Il problema è che non ho idea di come incollarli nella quasiquote finale. La documentazione dice che dovrei fare qualcosa di simile:

q"{ case ..$cases }" 

ma non funziona se lo faccio.

C'è un modo per creare una partialFunction da un elenco di questo tipo?

Grazie per qualsiasi aiuto.

+0

Credo che questo sia l'approccio corretto. Che errore hai esattamente? – Odomontois

+0

Anche il tuo pattern è un po 'strano 'x => 1' mathes qualsiasi espressione, se fai riferimento ad un valore locale chiamato' x' dovresti usare '\' x \ '=> 1' come patern – Odomontois

+1

L'errore è il seguente : eccezione durante l'espansione macro: java.lang.IllegalArgumentException: scala.collection.immutable.List (case (x @ _) => 1, case _ => 0) non è una rappresentazione valida del caso di corrispondenza del modello. –

risposta

2

le seguenti opere per me con 2.11.2:

import scala.reflect.macros.Context 
object Macros { 
    def partial: PartialFunction[Int, Int] = macro partialImpl 
    def partialImpl(c: Context): c.Expr[PartialFunction[Int, Int]]= { 
     import c.universe._ 
     val cases = cq"x => 1 " :: cq"_ => 0 " :: Nil 
     val pf = q"{ case ..$cases } : PartialFunction[Int, Int]" 
     c.Expr[PartialFunction[Int, Int]](pf) 

    } 
} 

Poi si può chiamare Macros.partial(1), per esempio, o Macros.partial.isDefinedAt(2).

Si noti che per fare questo lavoro, ho dovuto utilizzare esplicitamente PartialFunction[Int, Int] nella quasiquote q"{ case ..$cases } : PartialFunction[Int, Int]". Non ha funzionato senza la definizione del tipo esplicito (altrimenti assume PartialFunction[Any, Int]).

Here è la specifica per quasiquote Sintassi per funzioni parziali. Funziona come un albero di pura sintassi, ma a quanto pare non può essere interpretato come un'espressione scritta tranne PartialFunction[Any, T] da una macro, a meno che il tipo non sia reso esplicito.

+0

Le funzioni anon della corrispondenza di modello possono essere Function o PartialFunction a seconda del tipo previsto. –

+0

Il tuo codice ha un bug: 'PartialFunction [Int, Int] {case ...}' creerà una PartialFunction che è definita sull'intero dominio. Quello che vuoi è invece '{case ...}: PartialFunction [Int, Int]' –

+0

True. Buona pesca. Fisso. –