让我说我有
trait fooTrait[T] {
def fooFn(x: T, y: T) : T
}
我希望用户能够使用自己定义的fooFn主体快速声明fooTrait的新实例。理想情况下,我想要像
这样的东西val myFoo : fooTrait[T] = newFoo((x:T, y:T) => x+y)
上班。但是,我不能只做
def newFoo[T](f: (x:T, y:T) => T) = new fooTrait[T] { def fooFn(x:T, y:T):T = f(x,y); }
因为它使用闭包,因此在程序多次运行时会产生不同的对象。我真正需要的是能够获取newFoo返回的对象的classOf,然后可以在不同的机器上构造它。我该怎么办?
如果您对该用例感兴趣,我正在尝试为Hadoop编写一个允许您执行的Scala包装器
IO("Data") --> ((x: Int, y: Int) => (x, x+y)) --> IO("Out")
中间的东西需要变成一个实现特定接口的类,然后可以在不同的机器上实例化(执行相同的jar文件)。只需要类名。
请注意,Scala使用转换的语法糖做正确的事(x:Int)=> x + 5到Function1的一个实例。我的问题是我是否可以在不破坏Scala内部的情况下复制此内容。如果这是lisp(我已经习惯),这将是一个简单的编译时宏...:嗅探:
答案 0 :(得分:2)
快速建议:为什么不尝试创建隐式def转换FunctionN对象到 - >所期望的特征?方法
我希望你不必为此使用任何宏!
答案 1 :(得分:2)
这是一个与您在问题中列出的语法相匹配并序列化/执行anon-function的版本。请注意,这会序列化Function2对象的状态,以便可以在另一台计算机上还原序列化版本。只是类名不足,如解决方案所示。
你应该制作自己的编码/解码功能,即使只是包含你自己的Base64实现(不依赖于Sun的热点)。
object SHadoopImports {
import java.io._
implicit def functionToFooString[T](f:(T,T)=>T) = {
val baos = new ByteArrayOutputStream()
val oo = new ObjectOutputStream(baos)
oo.writeObject(f)
new sun.misc.BASE64Encoder().encode(baos.toByteArray())
}
implicit def stringToFun(s: String) = {
val decoder = new sun.misc.BASE64Decoder();
val bais = new ByteArrayInputStream(decoder.decodeBuffer(s))
val oi = new ObjectInputStream(bais)
val f = oi.readObject()
new {
def fun[T](x:T, y:T): T = f.asInstanceOf[Function2[T,T,T]](x,y)
}
}
}
// I don't really know what this is supposed to do
// just supporting the given syntax
case class IO(src: String) {
import SHadoopImports._
def -->(s: String) = new {
def -->(to: IO) = {
val IO(snk) = to
println("From: " + src)
println("Applying (4,5): " + s.fun(4,5))
println("To: " + snk)
}
}
}
object App extends Application {
import SHadoopImports._
IO("MySource") --> ((x:Int,y:Int)=>x+y) --> IO("MySink")
println
IO("Here") --> ((x:Int,y:Int)=>x*y+y) --> IO("There")
}
/*
From: MySource
Applying (4,5): 9
To: MySink
From: Here
Applying (4,5): 25
To: There
*/
为了说服自己,类名不足以在另一台机器上使用该功能,请考虑下面的代码创建100个不同的功能。计算文件系统上的类并进行比较。
object App extends Application {
import SHadoopImports._
for (i <- 1 to 100) {
IO(i + ": source") --> ((x:Int,y:Int)=>(x*i)+y) --> IO("sink")
}
}