2009-10-13 156 views
4

编译时的对象创建语法糖可以说我有在斯卡拉

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:强度)=> X + 5至功能1的一个实例。我的问题是我是否可以在不攻击Scala内部部件的情况下复制这些内容。如果这是lisp(就像我习惯的那样),这将是一个微不足道的编译时宏...:嗅探:

+0

想要将函数序列化到远程机器吗?通过实例化类“从类名”是什么意思?这个例子中的班级或班级名称是什么? – 2009-10-14 22:34:07

+0

基本上,我想要的是让代码Foo(Int => Int):返回一些东西的字符串。然后,在加载了相同jar文件的另一台机器上,我想在该String上运行Bar(s:String):FooTrait [Int]并让Bar(Foo(fn))返回一个具有fn作为方法的对象。这样做的一个方法是def Foo(obj:FooTrait [Int])= classOf(obj).toString,然后让Bar从类名创建一个新的类实例,但这需要将一个类传递给Foo,而不是拉姆达。 – bsdfish 2009-10-15 19:28:30

回答

2

这里有一个匹配的你在问题中列出什么语法和串行/执行匿名函数的版本。请注意,这会序列化Function2对象的状态,以便可以在另一台计算机上恢复序列化版本。只是类名不够,如下面的解决方案所示。

你应该让自己的编码/解码功能,如果连只包括您自己的Base64实现(不依赖Sun的Hotspot)。

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") 
    } 
} 
+0

非常感谢!我完全同意你的观点,在我所说的背景下,类名是微不足道的。这看起来很有希望! – bsdfish 2009-10-16 10:05:46

2

快速建议:为什么不尝试创建一个隐式def转换FunctionN对象 - >方法期望的特征。

我希望你将不必使用任何宏观此!

+0

这就是主意。但隐含def应该怎么说呢?我所能想到的正是我为myFoo所定义的,这不是编译而是运行时。 – bsdfish 2009-10-13 04:43:57