簡體   English   中英

用於Scala中編譯時對象創建的語法糖

[英]Syntactic sugar for compile-time object creation in Scala

可以說我有

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(我已經習慣了),這將是一個簡單的編譯時宏......:嗅探:

快速建議:為什么不嘗試創建一個隱式def轉換FunctionN對象到 - >方法所期望的特征。

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

這是一個與您在問題中列出的語法相匹配並序列化/執行anon-function的版本。 請注意,這會序列化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")
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM