2

次のScalaコードをすべてJavaで表現したいと思います。

object TupleDemo {
  val tuple = (3, "Hello, world! ")

  /** @return str replicated x times */
  def foo(x: Int, str: String) = str * x

  val tupledFoo1 = (foo _).tupled // partially applied function

  val tupledFoo2 = Function.tupled(foo _) // desugared syntax for same partially applied function
}

object TupleDemoApp extends App {
  import TupleDemo._

  println(tupledFoo1(tuple)) // Hello, world! Hello, world! Hello, world!
  println(tupledFoo2(tuple)) // Hello, world! Hello, world! Hello, world!
}

これは、Javaに相当するものについて私が理解できる限りのことです。

import scala.Function1;
import scala.Function2;
import scala.Tuple2;
import scala.collection.immutable.WrappedString;
import scala.runtime.AbstractFunction2;

public class JavaTupleDemo {
   /** @return str replicated x times */
   static final Function2<Integer, String, String> foo = new AbstractFunction2<Integer, String, String>() {
       public String apply(Integer x, String str) {
           return new WrappedString(str).$times(x);
       }

       // perhaps the types for this method are incorrect?
       public Function1<Tuple2<Integer, String>, String> tupled(Tuple2 tuple2) {
           return null; // what to write here instead of null?
       }
   };

  public static void main(String[] args) {
      // works: Invoke tupled function defined in Scala from Java using Tuple2 defined in Java
      Tuple2<Object, String> tuple = new Tuple2<Object, String>(3, "Hello, World! ");
      System.out.println(TupleDemo.tupledFoo1().apply(tuple));

      // works: Invoke regular function defined in Java from Java
      System.out.println(JavaTupleDemo.foo.apply(3, "Hello, planet! "));

      // stumped: Invoke tupled function defined in Java from Java using both the Scala and the Java Tuple2 instances
  }
}
4

2 に答える 2

4

tupledFunction2はで(したがってで)実装されているAbstractFunction2ため、ここで定義する必要はありません。次のように記述できます。

import scala.Function;
import scala.Function2;
import scala.Tuple2;
import scala.collection.immutable.WrappedString;
import scala.runtime.AbstractFunction2;

public class JavaTupleDemo {
  static final Function2<Integer, String, String> foo =
    new AbstractFunction2<Integer, String, String>() {
      public String apply(Integer x, String str) {
        return new WrappedString(str).$times(x);
      }
    };

  public static void main(String[] args) {
    Tuple2<Integer, String> tuple =
      new Tuple2<Integer, String>(3, "Hello, World! ");

    System.out.println(JavaTupleDemo.foo.tupled().apply(tuple));
    System.out.println(Function.tupled(JavaTupleDemo.foo).apply(tuple));
  }
}

foo.tupled()Javaはこれをメソッドと見なし、どちらの場合もを取得するため、を記述する必要があることに注意してくださいFunction1。したがって、を記述する.apply(tuple)必要がありますが、それ以外の点では、これは基本的にScalaバージョンと同じです。


Integerタプルに:として入力することについての質問に対処するには、これを処理する最も簡単な方法( Scala側で明示的にObject作成できない、または作成したくない場合)はおそらく次のとおりです。Integer

Tuple2<Object, String> scalaTuple = TupleDemo.tuple();

Tuple2<Integer, String> tuple = new Tuple2<Integer, String>(
  (Integer) scalaTuple._1(),
  scalaTuple._2()
);

つまり、タプルを分解し、キャストしてInteger、元に戻します。

于 2012-12-22T02:51:59.783 に答える
0

Travis Brownの回答の問題は、彼がすべてのコードを含んでいないことです。これがコンパイルされない完全なコードです。

import scala.Function;
import scala.Function2;
import scala.Tuple2;
import scala.collection.immutable.WrappedString;
import scala.runtime.AbstractFunction2;

public class JavaTupleDemo {
   /** tupled() is implemented in Function2 (and therefore in AbstractFunction2)
    * @return str replicated x times */
   static final Function2<Integer, String, String> foo = new AbstractFunction2<Integer, String, String>() {
       public String apply(Integer x, String str) {
           return new WrappedString(str).$times(x);
       }
   };

  public static void main(String[] args) {
      // Invoke tupled function defined in Scala from Java using Tuple2 defined in Java
      Tuple2<Object, String> tuple = new Tuple2<Object, String>(3, "Hello, World! ");
      System.out.println(TupleDemo.tupledFoo1().apply(tuple));

      // Invoke regular function defined in Java from Java
      System.out.println(JavaTupleDemo.foo.apply(3, "Hello, planet! "));

      // Invoke tupled function defined in Java from Java using both the Scala and the Java Tuple2 instances
      System.out.println(JavaTupleDemo.foo.tupled().apply(tuple));
      System.out.println(Function.tupled(JavaTupleDemo.foo).apply(tuple));
  }
}

エラーメッセージは次のとおりです。

error: method apply in interface Function1<T1,R> cannot be applied to given types;
required: Tuple2<Integer,String>
found: Tuple2<Object,String>
reason: actual argument Tuple2<Object,String> cannot be converted to Tuple2<Integer,String> by method invocation conversion
where T1,R are type-variables:
T1 extends Object declared in interface Function1
R extends Object declared in interface Function1

タプルをTuple2<Integer、String>に単純にキャストすることはできません。次のことを試してみてください。

System.out.println(JavaTupleDemo.foo.tupled().apply((Tuple2<Integer, String>)tuple));
System.out.println(Function.tupled(JavaTupleDemo.foo).apply((Tuple2<Integer, String>)tuple));

エラーメッセージは次のとおりです。

error: inconvertible types
required: Tuple2<Integer,String>
found:    Tuple2<Object,String>

このコンパイルを行う唯一の方法は、本当に厄介なことを行うことです。最初にタプルをオブジェクトにキャストし、次にタプル2 <整数、文字列>にキャストします。

System.out.println(JavaTupleDemo.foo.tupled().apply((Tuple2<Integer, String>)((Object)javaTuple)));
System.out.println(Function.tupled(JavaTupleDemo.foo).apply((Tuple2<Integer, String>)((Object)javaTuple)));

これを行うためのより良い方法はありますか?

于 2012-12-22T21:13:28.513 に答える