Scala 类型参数与WeakTypeTag反射不匹配+;准液化(我想!)
受此启发,我尝试使用宏来创建一些“智能构造函数” 给定Scala 类型参数与WeakTypeTag反射不匹配+;准液化(我想!),scala,scala-macros,scala-reflect,Scala,Scala Macros,Scala Reflect,受此启发,我尝试使用宏来创建一些“智能构造函数” 给定 包mypkg [答] 案例类Ohayo[A,B](A:(A,B))扩展了Hello[A] 及 val smartConstructors=FreeMacros.liftConstructors[Hello] 宏应该找到Hello的所有子类,查看它们的构造函数,并提取一些元素来填充此树中的“智能构造函数”: q”“” def$methodName[…$typeParams](…$ParamList):$baseType= $company
包mypkg
[答]
案例类Ohayo[A,B](A:(A,B))扩展了Hello[A]
及
val smartConstructors=FreeMacros.liftConstructors[Hello]
宏应该找到Hello
的所有子类,查看它们的构造函数,并提取一些元素来填充此树中的“智能构造函数”:
q”“”
def$methodName[…$typeParams](…$ParamList):$baseType=
$companysymbol[…$typeArgs](…$argLists)
"""
我希望得到:
val smartConstructors=新建{
def ohayo[A,B](A:(A,B)):Hello[A]=ohayo[A,B](A)
}
但是,你可以得到:
错误:类型不匹配;
发现:(A(Ohayo类),B(Ohayo类))
所需:((一些其他)A(在Ohayo类中),(一些其他)B(在Ohayo类中))
val liftedConstructors=FreeMacros.liftConstructors[Hello]
乍一看,这棵树看起来还不错:
scala>q“新建{..$welltypted}”
res1:美国树=
{
最后一个类$anon扩展了scala.AnyRef{
def()={
超级(;
()
};
def ohayo[A,B](A:(A,B)):net.arya.constructors.Hello[A]=ohayo[A,B](A)
};
新$anon()
}
但我想它在无形中不是。如果我天真地尝试用info.typeParams.map(p=>TypeName(p.name.toString))
刷新typeParams,那么在执行准量化时,我会得到“无法拼接as-type参数”
我哪里做错了?谢谢你看
-雅利雅
导入scala.language.experimental.macros
导入scala.reflect.api.Universe
导入scala.reflect.macros.whitebox
类FreeMacros(val c:whitebox.Context){
导入c.universe_
导入自由宏_
def liftedImpl[F[]](隐式t:c.WeakTypeTag[F[]]):树={
val atc=t.tpe
val childSymbols:Set[ClassSymbol]=子类符号(c.universe)(atc.typeSymbol.asClass)
val welltypted=childSymbols.map(ctorsForSymbol(c.universe)(atc)).unzip
q“新建{..${wellTyped}}”
}
}
对象自由宏{
def liftConstructors[F[]]:Any=宏FreeMacros.liftedImpl[F]
def smartName(名称:字符串):字符串=(
name.toList匹配{
案例h::t=>h.toLower::t
案例Nil=>Nil
}
).mkString
def子类别符号(u:Universe)(根:u.ClassSymbol):设置[u.ClassSymbol]={
val subclass=root.knownDirectSubclass
val cast=subclasses.map(u.asInstanceOf[u.ClassSymbol])
val partitioned=mapped.partition(uu.isCaseClass)
分区匹配{
case(caseClasses,regularClasses)=>caseClasses++regularClasses.flatMap(r=>subseclassssymbols(u)(r))
}
}
def-ctorsForSymbol(u:Universe)(atc:u.Type)(案例类别:u.ClassSymbol):(u.DefDef,u.DefDef)={
进口美国_
导入内部_
//这些都没用
//def clearTypeSymbol(s:Symbol):TypeSymbol=内部.newTypeSymbol(NoSymbol,s.name.toTypeName,s.pos,if(s.isImplicit)Flag.IMPLICIT else NoFlags)
//def clearTypeSymbol2(s:Symbol):TypeSymbol=内部.newTypeSymbol(NoSymbol,s.name.toTypeName,NoPosition,if(s.isImplicit)Flag.IMPLICIT else NoFlags)
//def clearTypeDef(d:TypeDef):TypeDef=internal.TypeDef(cleartypessymbol(d.symbol))
val companionSymbol:Symbol=caseClass.companion
val info:Type=caseClass.info
val primaryCtor:Symbol=caseClass.primaryConstructor
val方法=PrimaryActor.asMethod
val typeParams=info.typeParams.map(internal.typeDef()
//val typeParams=info.typeParams.map(s=>typeDef(newTypeSymbol(NoSymbol,s.name.toTypeName,NoPosition,NoFlags)))
//val typeParams=info.typeParams.map(s=>internal.typeDef(clearTypeSymbol2)))
val-typeArgs=info.typeParams.map(uz.name)
val paramLists=method.paramLists.map(0.map(internal.valDef(0)))
val argLists=method.paramLists.map(u.map(u.asTerm.name))
val baseType=info.baseType(atc.typeSymbol)
val列表(returnType)=baseType.typeArgs
val methodName=TermName(smartName(caseClass.name.toString))
瓦尔好打字=
q”“”
def$methodName[…$typeParams](…$ParamList):$baseType=
$companysymbol[…$typeArgs](…$argLists)
"""
优秀的
}
}
另外,我一直在试验toolbox.untypecheck/typecheck per,但还没有找到一个有效的组合。您需要使用
clas.typeArgs.map(_.toString).map(name => {
TypeDef(Modifiers(Flag.PARAM),TypeName(name), List(),TypeBoundsTree(EmptyTree, EmptyTree))
}
替换
info.typeParams.map(p=>TypeName(p.name.toString))
这是我的密码
object GetSealedSubClass {
def ol3[T]: Any = macro GetSealedSubClassImpl.ol3[T]
}
class GetSealedSubClassImpl(val c: Context) {
import c.universe._
def showInfo(s: String) =
c.info(c.enclosingPosition, s.split("\n").mkString("\n |---macro info---\n |", "\n |", ""), true)
def ol3[T: c.WeakTypeTag]: c.universe.Tree = {
//get all sub class
val subClass = c.weakTypeOf[T]
.typeSymbol.asClass.knownDirectSubclasses
.map(e => e.asClass.toType)
//check type params must ia s sealed class
if (subClass.size < 1)
c.abort(c.enclosingPosition, s"${c.weakTypeOf[T]} is not a sealed class")
// get sub class constructor params
val subConstructorParams = subClass.map { e =>
//get constructor
e.members.filter(_.isConstructor)
//if the class has many Constructor then you need filter the main Constructor
.head.map(s => s.asMethod)
//get function param list
}.map(_.asMethod.paramLists.head)
.map(_.map(e => q"""${e.name.toTermName}:${e.info} """))
val outfunc = subClass zip subConstructorParams map {
case (clas, parm) =>
q"def smartConstructors[..${
clas.typeArgs.map(_.toString).map(name => {
TypeDef(Modifiers(Flag.PARAM), TypeName(name), List(), TypeBoundsTree(EmptyTree, EmptyTree))
})
}](..${parm})=${clas.typeSymbol.name.toTermName} (..${parm})"
}
val outClass =
q"""
object Term{
..${outfunc}
}
"""
showInfo(show(outClass))
q"""{
$outClass
Term
}
"""
}
}
sealed trait Hello[A]
case class Ohayo[A, B](a: (A, B)) extends Hello[A]
object GetSealed extends App {
val a = GetSealedSubClass.ol3[Hello[_]]
val b=a.asInstanceOf[ {def smartConstructors[A, B](a: (A, B)): Ohayo[A, B]}].smartConstructors(1, 2).a
println(b)
}