单个类的所有方法的函数类型 - 在Scala中 [英] Function type of all methods of a single class - in Scala
问题描述
不知道如何正确地表达这个(因此,如何查看它),但这里有:
我理解应用于对象的方法如何变成一个函数对象。例如:
case class User(name:String,age:Int)
val user = User( ,0)
user.name _ //()=>字符串
所以,如果我有一个方法 def meth(f: => String)
,我可以这样做: meth(user.name _)
是否可以定义一个类型,它具有类的方法作为实例 换句话说, 谢谢! 我想要做这样的事情的唯一方法就是使用宏的。我曾经创建了一个执行以下操作的宏(请注意,当前实现中的一些细节已更改,因此为空)。 在代码中,您可以像这样使用它: 大约一年前有效的代码可以在这里找到: ee / scala / staticReflection / Metadata.scala 的。详细了解现在的宏。 如果这是您要查找的内容,请让我知道,以便我可以查看是否可以将原件转换为正常版本。 我设法让旧的工作。要使用它,只需将代码复制到单独的项目中(我使用Eclipse),然后通过 全部应用上面的东西的原始海报的问题。您可以像这样使用它。 请注意,解决方案与建议的不同,但在 Not sure how to properly formulate this (hence, how to look it up), but here goes: I understand how a method applied to an object can become a function object. For example: So, if I had a method Is is possible to define a type that has as instances the methods of class In order words, what would the type of Thanks! I guess the only way to do something like that is to use macro's. I once created a macro that does the following (note that some details changed in the current implementation and thus are empty). In code you would then use it like this: The code as it was valid almost a year ago can be found here: ee/scala/staticReflection/Metadata.scala. More info about macros as they are now. If this is what you were looking for, please let me know so I can see if I can convert the original to a working version. I managed to get the old one working. To use it simply copy-past the code into a separate project (I use Eclipse) and then link the projects via the
To apply all of the above stuff to the question of the original poster. You could use it like this Note that the solution is different from what was proposed, but within the 这篇关于单个类的所有方法的函数类型 - 在Scala中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
(从这些方法获得的函数对象,更确切地说)
f
def meth(f:???)是,为了能够做到这一点: meth(user.name _ )
和 meth(user.age _)
case class Metadata(实例:AnyRef,name:String){
def value = ??? //(使用反射来调用`instance`上的`name`
}
对象元数据扩展((AnyRef,String)=>元数据){
隐式def anyToMetadata(sym:Any):Metadata =
macro MetadataMacro.anyToMetadataImpl
}
$ b $ private [staticReflection] object MetadataMacro {
def anyToMetadataImpl(c :Context)(sym:c.Expr [Any]):c.Expr [Metadata] = {
import c.universe._
val metadata = // match树并创建适当的元数据实例
c.Expr(元数据)
}
}
case class User :字符串)
def test(元数据:元数据){
println(metadata.name + - >+ metadata.value)
}
val u = User(test)
test(u.name)// name - >测试
< hr>
编辑
Java Build Path
链接项目。工作版本:
包ee.scala.staticReflection
导入scala.language.experimental.macros
import scala.reflect.macros.Context
import language.implicitConversions
case class元数据(实例:AnyRef,name:String){
//关于为了改进这部分,欢迎
val runtimeUniverse = scala.reflect.runtime.universe
val mirror = runtimeUniverse.runtimeMirror(getClass.getClassLoader)
val instanceMirror = mirror.reflect(instance)
val method = instanceMirror.symbol.selfType.member(runtimeUniverse newTermName name).asMethod
val methodMirror = instanceMirror.reflectMethod(method)
def value = methodMirror()
元数据扩展((AnyRef,String)=>元数据){
implicit def anyToMetadata(sym:Any):Metadata = macro MetadataMacro.anyToMetadataImpl
}
private [staticReflection] object MetadataMacro {
def anyTo MetadataImpl(c:Context)(sym:c.Expr [Any]):c.Expr [Metadata] = {
import c.universe._
def createMetadataInstance(select:Select) :Tree =
treeBuild.mkMethodCall(
c.mirror.staticModule(ee.scala.staticReflection.Metadata),
newTermName(apply),
List(select .qualifier,Literal(常量(select.name.toString))))
val元数据= sym.tree匹配{
//正常选择
case select:Select => ; createMetadataInstance(select)
//可以是使用右关联运算符的调用
case Ident(name)=>
c.enclosingMethod.collect {
case ValDef(_,refName,_,select:Select)if refName == name => createMetadataInstance(select)
}
.headOption
.getOrElse(抛出新的异常(无法找到ValDef for+ name))
case _ => (无法创建元数据)
}
c.Expr(元数据)
}
}
编辑2
case class User(name:String,age:Int)
val user = User (元数据:元数据)= {
println(metadata.name + - >+ metadata.value)
} $ b(,0)
def meth
$ b meth(user.name)
meth(user.age)
meth
函数中,您可以执行相同的操作(更均匀一些)。case class User(name: String, age: Int)
val user = User("", 0)
user.name _ // () => String
def meth(f: () => String)
, I could do: meth(user.name _)
User
?
(the function objects obtained from these methods, more precisely) f
in def meth(f: ???)
be, in order to be able to do this: meth(user.name _)
and meth(user.age _)
case class Metadata(instance: AnyRef, name: String) {
def value = ??? // use reflection to invoke `name` on `instance`
}
object Metadata extends ((AnyRef, String) => Metadata) {
implicit def anyToMetadata(sym: Any): Metadata =
macro MetadataMacro.anyToMetadataImpl
}
private[staticReflection] object MetadataMacro {
def anyToMetadataImpl(c: Context)(sym: c.Expr[Any]): c.Expr[Metadata] = {
import c.universe._
val metadata = // match the tree and create the appropriate metadata instance
c.Expr(metadata)
}
}
case class User(name:String)
def test(metadata:Metadata) {
println(metadata.name + "->" + metadata.value)
}
val u = User("test")
test(u.name) // name -> test
Edit
Java Build Path
. Working version:package ee.scala.staticReflection
import scala.language.experimental.macros
import scala.reflect.macros.Context
import language.implicitConversions
case class Metadata(instance: AnyRef, name: String) {
// any comments on how to improve this part are welcome
val runtimeUniverse = scala.reflect.runtime.universe
val mirror = runtimeUniverse.runtimeMirror(getClass.getClassLoader)
val instanceMirror = mirror.reflect(instance)
val method = instanceMirror.symbol.selfType.member(runtimeUniverse newTermName name).asMethod
val methodMirror = instanceMirror.reflectMethod(method)
def value = methodMirror()
}
object Metadata extends ((AnyRef, String) => Metadata) {
implicit def anyToMetadata(sym: Any): Metadata = macro MetadataMacro.anyToMetadataImpl
}
private[staticReflection] object MetadataMacro {
def anyToMetadataImpl(c: Context)(sym: c.Expr[Any]): c.Expr[Metadata] = {
import c.universe._
def createMetadataInstance(select: Select): Tree =
treeBuild.mkMethodCall(
c.mirror.staticModule("ee.scala.staticReflection.Metadata"),
newTermName("apply"),
List(select.qualifier, Literal(Constant(select.name.toString))))
val metadata = sym.tree match {
//normal select
case select: Select => createMetadataInstance(select)
//could be a call using a right associative operator
case Ident(name) =>
c.enclosingMethod.collect {
case ValDef(_, refName, _, select: Select) if refName == name => createMetadataInstance(select)
}
.headOption
.getOrElse(throw new Exception("Could not find ValDef for " + name))
case _ => throw new Exception("Could not create metadata")
}
c.Expr(metadata)
}
}
Edit 2
case class User(name: String, age: Int)
val user = User("", 0)
def meth(metadata: Metadata) = {
println(metadata.name + "->" + metadata.value)
}
meth(user.name)
meth(user.age)
meth
function you can do the same (a bit more even).