2009-10-13 161 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