0

I'm pretty sure what I'd like to do is probably not possible and not a good idea anyway. Nonetheless, here it is.

I would like to find a generic way of transforming any method on any class into a function that takes as arguments an instance of the class and the parameters of the method and calls the method on the instance with the specified parameters (which is basically how method calls work at a low-level: the object instance is a hidden parameter pushed by the compiler on the stack frame)

Example:

Given

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

I would like to have something like:

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

Such that:

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

Which would allow something like:

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) _)

One example where something like that could be useful follows:

Imagine you have:

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

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

but you'd like an arguably cleaner:

import OptionUtils.getOrElse

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

Now, I've defined that getOrElse manually as:

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

But would like to be able to do automatically define such a methods for all (or any given selection) of methods in a specified class. Ideally I'd have something like:

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

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

Any suggestions/comments?

  • yes it's bad idea, but you can do that - just use reflection http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html – dk14 Apr 22 '15 at 23:06
  • possible duplicate of [Is there any Scala feature that allows you to call a method whose name is stored in a string?](http://stackoverflow.com/questions/2060395/is-there-any-scala-feature-that-allows-you-to-call-a-method-whose-name-is-stored) – dk14 Apr 22 '15 at 23:11

1 Answers1

1

You can use Java relection for this (here is scala code)

Or Scala reflection:

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
Community
  • 1
  • 1
dk14
  • 22,206
  • 4
  • 51
  • 88