mercredi 22 avril 2015

Scala class method to function with class instance as parameter

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?





Aucun commentaire:

Enregistrer un commentaire