Jak uzyskać makro scala, aby zastąpić wywołanie metody?Jak uzyskać makro scala, aby zastąpić wywołanie metody
Moim celem jest stworzenie cechy o nazwie ToStringAdder
. Przypuśćmy, że mam obiekt x
z tą cechą, a kiedy zadzwonię pod numer x.add(any)
, chcę, aby makro faktycznie wywoływało x.add(any, string)
, gdzie ciąg jest ciągiem reprezentującym AST. (Jest tak, że mogę mieć ładne tostring
, gdy "dowolne" jest funkcją).
- Pisałem makr zawartych w dokumentacji http://docs.scala-lang.org/overviews/macros/overview.html,
- Czytaj http://docs.scala-lang.org/sips/pending/self-cleaning-macros.html
- Przeczytaj pdfs http://scalamacros.org/paperstalks/2013-04-22-LetOurPowersCombine.pdf.
- Szukałem na kod w https://github.com/retronym/macrocosm/blob/master/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala
- I kod w https://github.com/pniederw/expecty/tree/master/src/main/scala/org/expecty, ale przykro mi powiedzieć, że nie Grok to wszystko
- miałem spojrzeć na scaladoc, ale. ..woo..To skomplikowane ... Podejrzewam, że potrzebowałbym trochę czasu, aby przyspieszyć działanie kompilatora.
Z wyjątkiem Expektuj wszystkie te przykłady, które widziałem, efektywnie używają wywołań metod statycznych: obiekt, na który wywoływane jest makro, nie jest używany. Expecty ma następującą metodę, która daje mi wskazówkę, jak wykryć "ukryty to", ale nie mogłem znaleźć sposobu, aby odwołać się do niego w reify połączenia.
private[this] def recordAllValues(expr: Tree): Tree = expr match {
case New(_) => expr // only record after ctor call
case Literal(_) => expr // don't record
// don't record value of implicit "this" added by compiler; couldn't find a better way to detect implicit "this" than via point
case Select([email protected](_), y) if getPosition(expr).point == getPosition(x).point => expr
case _ => recordValue(recordSubValues(expr), expr)
}
Jak mogę zastąpić wywołanie obiektu, do którego zostało wywołane makro. Kod mam w tej chwili jest poniżej, a to jest kod w zaproszeniu zreifikować że musi być sortowane
trait ToStringAdder {
def add(param: Any): Any = macro ToStringAdder.toStringAndValueImpl
def add(param: Any, toStringBasedOnAST: String): Any ; //This is the actual method I want the above method call to be replaced by
}
object ToStringAdder {
def toStringAndValueImpl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = {
import c.universe._
val paramRep = show(param.tree)
val paramRepTree = Literal(Constant(paramRep))
val paramRepExpr = c.Expr[String](paramRepTree)
//need to put something here
reify { c.someMethodCall("something to represent the method any", param.splice, paramRepExpr.splice) }
}
}
To jest naprawdę ładny pytanie jeśli rozumiem go poprawnie. Sądzę, że chodzi o to, że przy użyciu toString na "funkcji", która zwraca unikalny AST, można zaimplementować operatora równości w 'Function's. Można wtedy robić niesamowite rzeczy, na przykład nie martwić się powielaniem funkcji w "liście" - wystarczy wywołać 'toSet'. – samthebest