2012-12-12 9 views
72

Ich fange mit einem Beispiel an. Hier ist ein Äquivalent von List.fill für Tupeln als Makro in Scala 2.10:Dokumentieren Scala 2.10 Makros

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

object TupleExample { 
    def fill[A](arity: Int)(a: A): Product = macro fill_impl[A] 

    def fill_impl[A](c: Context)(arity: c.Expr[Int])(a: c.Expr[A]) = { 
    import c.universe._ 

    arity.tree match { 
     case Literal(Constant(n: Int)) if n < 23 => c.Expr(
     Apply(
      Select(Ident("Tuple" + n.toString), "apply"), 
      List.fill(n)(a.tree) 
     ) 
    ) 
     case _ => c.abort(
     c.enclosingPosition, 
     "Desired arity must be a compile-time constant less than 23!" 
    ) 
    } 
    } 
} 

Wir können diese Methode wie folgt:

scala> TupleExample.fill(3)("hello") 
res0: (String, String, String) = (hello,hello,hello) 

Dieser Typ ist eine seltsame Vogel in ein paar Punkten. Erstens muss das Argument arity eine literale Ganzzahl sein, da wir es zur Kompilierungszeit verwenden müssen. In früheren Versionen von Scala gab es (so weit ich weiß) keine Möglichkeit für eine Methode, selbst zu bestimmen, ob eines ihrer Argumente ein kompilierbares Literal war oder nicht.

Zweitens, der Rückgabetyp is a lie -der statische Rückgabetyp enthält den spezifischen Arity- und Elementtyp, der durch die Argumente bestimmt wird, wie oben gezeigt.

Also, wie würde ich dieses Ding dokumentieren? Ich erwarte zu diesem Zeitpunkt nicht die Unterstützung von Scaladoc, aber ich hätte gerne ein Gefühl für Konventionen oder Best Practices (nicht nur, um sicherzustellen, dass die Fehlermeldungen zur Kompilierungszeit klar sind), die zu einer Makromethode führen würden möglicherweise bizarre Anforderungen - weniger überraschend für Benutzer einer Scala 2.10-Bibliothek.

Die reifste Demonstrationen des neuen Makro-Systems (zum Beispiel ScalaMock, Slick, die anderen aufgeführten here) bei der Methode Ebene noch relativ undokumentiert. Irgendwelche Beispiele oder Zeiger würden geschätzt werden, einschließlich solcher aus anderen Sprachen mit ähnlichen Makrosystemen.

+12

In Bezug auf ScalaMock, als Autor, wäre ich sehr dankbar für Vorschläge, wie ich die Dokumentation verbessern könnte. ScalaMock ist eigentlich ein DSL, also bedeutet die Dokumentation einzelner Methoden nicht unbedingt viel. Ich habe versucht, das DSL als Ganzes hier zu dokumentieren: http://scalamock.org/api/index.html#org.scalamock.package und es beginnt Dokumentation hier: http://www.paulbutcher.com/2012/10/scalamock3-step-by-step/Was könnte ich hinzufügen, das würde helfen? –

+2

@PaulButcher: Ich will ScalaMock nicht kritisieren, und ich habe die Antwort bearbeitet, um das klarer zu machen. Ich habe es sehr nützlich gefunden, Ihren Code zu lesen, da ich versucht habe, Scalas Makros zu verstehen, und ich denke, dass die High-Level-Dokumentation sehr klar ist. –

+8

Nichts für ungerechtfertigt. Aber ich würde definitiv alle Vorschläge für Verbesserungen begrüßen. –

Antwort

1

Ich denke, der beste Weg, dies zu dokumentieren, ist mit Beispielcode, wie Miles in seinem experimentellen macro based branch formlos gemacht hat.