2015-04-23 29 views
6

I zrozumieć podstawowe pojęcia makr w Scala, ale aktualnie nie uda się to zrobić (proste?) Praca:Znalezienie ukryte definicje metoda makro kontekście

  • Znajdź wszystkie ukryte def s/val s obecnie widoczne kompilator do przekształcenia z określonego typu w inny.

To, czego się spodziewałam, to List z obiektów lub coś podobnego. Już grałem z enclosingImplicits, ale zawsze mam pustą listę i nie wiem, gdzie szukać dalej.

Co należy zrobić, aby uzyskać listę, której szukam?

Odpowiedz

2

Nie może być tylko jeden niejawny od rodzaju A do B w kontekście (lub masz niejednoznaczną niejawny), więc jeśli chcesz go znaleźć:

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

def fImpl(c: Context): c.Expr[Unit] = { 
    import c.mirror._   
    println(c.inferImplicitValue(typeOf[Int])) 
    c.universe.reify(()) 
} 
def f = macro fImpl 

scala> f 
<empty> 

scala> implicit val a = 5 
a: Int = 5 

scala> f 
$line24.$read.$iw.$iw.$iw.$iw.a 

scala> implicit val b = 5 
b: Int = 5 

scala> f //result will be empty, but error printed to the log 
error: ambiguous implicit values: 
both value a of type => Int 
and value b of type => Int 
match expected type Int 
<empty> 

Aby znaleźć sposób niejawny:

def fImpl(c: Context): c.Expr[Unit] = { 
     import c.mirror._  
     println(c.inferImplicitValue(typeOf[String => Int]))   
     c.universe.reify(()) 
} 
def f = macro fImpl 

scala> f 
<empty> 

scala> implicit def aaa(a: String) = 5 
warning: there was one feature warning; re-run with -feature for details 
aaa: (a: String)Int 

scala> "A" : Int 
res10: Int = 5 

scala> f 
{ 
    ((a: String) => $line47.$read.$iw.$iw.$iw.$iw.$iw.$iw.aaa(a)) 
} 

Jeśli parametr silent jest domyślnie ustawiony na false (true), zostanie wygenerowany TypecheckException w przypadku błędu wnioskowania. Możesz więc go przeanalizować, aby znaleźć listę niejednoznacznych implicite.

P.S. Jeśli typ B jest nieznany - nie ma (udokumentowanego) sposobu na znalezienie wszystkich implikacji przy użyciu makr: openImplicits/enclosingImplicits szukających tylko implikacji materializowanych w kontekście makro-ekspansji - nie dla wszystkich, które istnieją w kontekście. Kompilator-wtyczka może pomóc, ale nie jest to takie proste.

Jeśli naprawdę zdecydujesz się wypróbować "sposób kompilowania wtyczek" - logika wyszukiwania implikacji jest zaimplementowana jako here. Here można znaleźć kompilator Context (nie taki sam jak makro) i jego pole implicitss, które zawiera wszystkie implikacje w kontekście (ale nie jest tak banalnie, aby uzyskać odpowiedni kontekst).


I nie powinienem wam ale jest to trudne i niebezpieczne Hack podnieść z makro Context na poziomie kompilatora i rób co chcesz:

scala> def fImpl(c: Context): c.Expr[Unit] = { 
|  val cc = c.asInstanceOf[reflect.macros.contexts.Context] 
|  println(cc.callsiteTyper.context.implicitss.flatten) 
|  c.universe.reify(()) 
| } 
fImpl: (c: reflect.macros.Context)c.Expr[Unit] 

scala> def f = macro fImpl 

scala> f //I've defined aaaaaaaa etc. implicits while playing with that 
List(aaaaaaaa: ?, lllllllllllllllllllllzzzz: ?, lllllllllllllllllllll: ?, lllllllllllllllllllll: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, b: ?, a: ?, macros: ?, RuntimeClassTag: 

W każdym razie, trzeba zweryfikuj listę ImplicitInfo, aby uzyskać implicite, czego szukasz i może nie być to banalne, jak widać ze źródeł Analizer, ale przynajmniej możliwe jest uzyskanie przybliżonego wyniku, który może być odpowiedni dla twoich potrzeb. Ale znowu lepiej jest zrobić to bardzo ostrożnie, ponieważ struktury, z którymi pracujesz, są zmienne, a metody nie są czyste. I, jak zauważył @Eugene Burmako, to rozwiązanie nie daje implicite z obiektu towarzyszącego.

+0

Przeczytałem to pytanie, mówiąc, że podano typ źródła, a cel nie był, w takim przypadku nie sądzę, że istnieje dobre rozwiązanie. –

+0

@Travis Brown W takim przypadku nie widzę żadnych, oprócz wtyczki kompilatora. – dk14

+0

@Travis Brown faktycznie istnieje nieudokumentowana niebezpieczna metoda wykonania tego (tak długo, jak inne sztuczki zależne od kompilatora) z makro :) Mój przykład daje wszystkie możliwe implicity, więc musi być dodatkowo analised (co jest również trudne) – dk14