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:Int) => x+5 を Function1 のインスタンスに変換するシンタックス シュガーを使用して正しいことを行うことに注意してください。私の質問は、Scala 内部をハッキングせずにこれを複製できるかどうかです。これが Lisp である場合 (私が慣れているように)、これは簡単なコンパイル時マクロになります ... :sniff:

4

2 に答える 2

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")
  }
}
于 2009-10-15T22:58:14.300 に答える
2

簡単な提案: FunctionN オブジェクトを --> メソッドが期待する特性に変換する暗黙の def を作成してみませんか。

これにマクロを使用する必要がないことを願っています。

于 2009-10-13T03:58:10.163 に答える