2015-04-22 67 views
0

我很确定我想要做的事可能是不可能的,也不是一个好主意。尽管如此,在这里。斯卡拉类的方法与类实例作为参数

我想找到一种将任何类的任何方法转换为一个函数的通用方法,该方法将类的实例和方法的参数作为参数,并使用指定的参数调用实例上的方法基本上方法调用在一个低级别的工作原理:对象实例是由编译器堆栈帧推隐藏参数)

实施例:

鉴于

class A { def foo(param1: Type1): TypeN } 

我想有是这样的:

def functor[X](methodName: String): (obj: X, methodParams: Types*) => TypeN 

这样的:

// Type (obj: A, param1: Type1) => TypeN 
val fooFn  = functor[A]("foo") 
val res: TypeN = fooFn(new A, new Type1) 

这将使类似:

def flip[A, B, C](fn: A => B => C): B => A => C = (b: B) => (a: A) => fn(a)(b) 

// Type (param1: Type1) => (obj: A) => TypeN 
val fooFl = flip(fooFn.curried) 
List(new A, new A).map(fooFl(new Type1) _) 

一个例子类似的东西,可能是有用的如下:

想象一下,你有:

val divide = (i: Int) => Try(2/i).toOption 

List(1, 0).map(i => divide(i).getOrElse(0)) 

但是你想一个可以说是清洁:

import OptionUtils.getOrElse 

List(1, 0).map(getOrElse(0) _ compose divide) 

现在,我已经定义了getOrElse手动为:

object OptionUtils { 
    def getOrElse[A](default: A)(option: Option[A]) = option.getOrElse(default) 
} 

不过想能够自动做这样的界定指定类中所有方法(或任何给定选择)的方法。理想情况下,我会喜欢:

val optionUtils: Utils[Option] = Utils(Option, List("getOrElse", "or")) 

optionUtils.getOrElse(None, 1) // = 1 
optionUtils.getOrElseFl(1)(None) // = 1 

任何建议/意见?

+0

是它的坏主意,但你可以做到这一点 - 只要使用反射的http://文档。 scala-lang.org/overviews/reflection/environment-universes-mirrors.html – dk14

+0

[有没有可以让你调用名称存储在字符串中的方法的Scala特性?](http:// stackoverflow。 COM /问题/ 2060395/IS-有-任何-Scala的特征,也就是说,允许,您对呼叫A-方法,其名称管理是存储) – dk14

回答

1

您可以使用Java relection这个(这里是scala代码)

或者斯卡拉反思:

import scala.reflect._, runtime.universe._ 

def functor[X: TypeTag: ClassTag, R](methodName: String)(obj: X) = { 
    val m = runtimeMirror(getClass.getClassLoader) 
    val method = typeTag[X].tpe.declaration(newTermName(methodName)).asMethod 
    val call = m.reflect(obj).reflectMethod(method) 
    (call.apply _) andThen (_.asInstanceOf[R]) 
} 

scala> functor[Option[Int], Int]("get") _ 
res19: Option[Int] => (Seq[Any] => Int) = <function1> 

scala> res19(Some(5))(Nil) 
res20: Int = 5