Let\'s consider a specific example. I have lots of functions that take a variable number of arguments, and return a Seq[T]
. Say:
def nonNeg(start: I
For 2 and more (in code below to 4) parameters you can use implicit parameters feature, for resolve result type by input parameter type
sealed trait FuncRes[F] {
type Param
type Result
def func : F => Param => Result
}
class Func[T, R](fn : T => R) {
trait FR[F, P] extends FuncRes[F] { type Param = P; type Result = R }
implicit def func2[T1,T2] = new FR[(T1,T2) => T, (T1,T2)] {
def func = f => p => fn(f.tupled(p))
}
implicit def func3[T1,T2,T3] = new FR[(T1,T2,T3) => T, (T1,T2,T3)] {
def func = f => p => fn(f.tupled(p))
}
implicit def func4[T1,T2,T3,T4] = new FR[(T1,T2,T3,T4) => T, (T1,T2,T3,T4)] {
def func = f => p => fn(f.tupled(p))
}
def makeFunc[F](f : F)(implicit ev : FuncRes[F]): ev.Param => ev.Result =
ev.func(f)
}
and after your def javaNonNeg = makeJava(nonNeg)
function will look like:
object asJavaFunc extends Func((_ : Seq[Int]).asJava)
import asJavaFunc._
def javaNonNeq = makeFunc(nonNeg _)
And of course it has some disadvantages, but generally it satisfy your needs.
It is possible to use Shapeless to avoid the boilerplate—you just need to turn the original method into a FunctionN
using plain old eta expansion, then convert to a function taking a single HList
argument, and then back to a FunctionN
with the new result type:
import java.util.{ List => JList }
import shapeless._, ops.function._
import scala.collection.JavaConverters._
def makeJava[F, A, L, S, R](f: F)(implicit
ftp: FnToProduct.Aux[F, L => S],
ev: S <:< Seq[R],
ffp: FnFromProduct[L => JList[R]]
) = ffp(l => ev(ftp(f)(l)).asJava)
And then:
scala> def nonNeg(start: Int, count: Int): Seq[Int] =
| Iterator.from(start).take(count).toSeq
nonNeg: (start: Int, count: Int)Seq[Int]
scala> val javaNonNeg = makeJava(nonNeg _)
javaNonNeg: (Int, Int) => java.util.List[Int] = <function2>
scala> javaNonNeg(1, 4)
res0: java.util.List[Int] = [1, 2, 3, 4]
javaNonNeg
is a Function2
, so from Java you can use javaNonNeg.apply(1, 4)
.