Stavím DSL pomocou škály, ktorá bude filtrovať údaje na základe stavu v DSL.
Funkcia filtra:
def filter(f: (Int) => (Int)) {
// find what is the name (age) of lambda passed
// query db with column name age and apply function f and return value
}
Použitie v DSL ako:
filter( (age) => age > 10 )
V DSL nemôžem nájsť spôsob, ako to zistiť age
sa používa, existuje nejaký spôsob?
Zatiaľ prechádzam reťazec ako prvý argument, ako je uvedené nižšie:
filter( "age", (age) => age > 10 )
a zmenil filter tak, aby sa prvý názov považoval za názov stĺpca.
Chcem zjednodušiť DSL.
odpovede:
3 pre odpoveď č. 1Jediným spôsobom, ako môžete v súčasnosti získať názov argumentu lambda, je deklarovanie makra Scala namiesto metódy Scala pre filter
, Makro dostane abstraktný syntaxový strom lambda namiesto samotného lambda, takže bude môcť analyzovať názov argumentov lambda.
Tu je veľmi minimálny príklad, ako to urobiť:
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
object MyFilter {
def filter(p: Int => Int): Unit = macro filterImpl
def filterImpl(c: Context)(p: c.Expr[Int => Int]): c.Expr[Unit] = {
import c.universe._
val Function(args, body) = p.tree
val ValDef(mods, name, tp, rhs) = args(0)
println(name)
reify {
()
}
}
}
Vyššie sme najprv importovali príslušné balíčky, aby sme povolili makrá. Potom definujeme def makro filter
spolu s jeho implementáciou filterImpl
, Nakoniec implementujeme makro - vzor porovnávame so stromom argumentu do a Function
strom, potom urobte prvý argument (args(0)
) a nakoniec vzor zodpovedá prvému argumentu do a ValDef
strom, aby bolo možné extrahovať meno.
Viac o makrách si môžete prečítať tu.