【问题标题】:Scala class method to function with class instance as parameterScala类方法以类实例作为参数起作用
【发布时间】:2015-06-30 18:38:27
【问题描述】:

我很确定我想做的事情可能是不可能的,也不是一个好主意。尽管如此,它就在这里。

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

例子:

给定

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

有什么建议/cmets?

【问题讨论】:

标签: scala reflection composition functor method-call


【解决方案1】:

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

或 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-04
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    相关资源
    最近更新 更多