8

のインスタンスがあり、scala.collection.immutable.Listそのメソッドを呼び出したいのですがmap、Java からです。

を提供する必要がありCanBuildFromます。

scala コレクションのコンパニオン オブジェクトの多くに暗黙的なインスタンスが含まれていることに気付きましたが、CanBuildFromどれを使用する必要があるのか​​わかりません。

ここに私のJavaコードがあります:

    Function1<WeatherData, BigDecimal> mapper = new AbstractFunction1<WeatherData, BigDecimal>(){
        @Override
        public BigDecimal apply(WeatherData data) {
            return data.getTemps().reduce(adder).divide(new BigDecimal(data.getTemps().size()));
        }
    };

    scala.collection.immutable.List<WeatherData> data = ...

    data.map(mapper, ???);

CanBuildFrom として何を渡す必要がありますか (2 番目のパラメーター?)

PS Scala 2.10-M5 を使用する

4

2 に答える 2

10

あなたは実際にあまり大騒ぎせずにJavaでタイプを正しくすることができます:

import scala.collection.Traversable;
import scala.collection.generic.CanBuildFrom;
import scala.collection.immutable.List;
import scala.collection.mutable.Builder;
import scala.runtime.AbstractFunction1;

public class ScalaMapTest {
  public static List<Integer> parseInts(List<String> xs) {
    final CanBuildFrom<List<?>, Integer, List<Integer>> builder =
      List.<Integer>canBuildFrom();

    return xs.map(
      new AbstractFunction1<String, Integer>() {
        public Integer apply(String s) {
          return Integer.parseInt(s);
        }
      },
      new CanBuildFrom<Traversable<String>, Integer, List<Integer>>() {
        public Builder<Integer, List<Integer>> apply() {
          return builder.apply();
        }

        public Builder<Integer, List<Integer>> apply(Traversable<String> from) {
          return builder.apply(from.toList());
        }
      }
    );
  }
}

それはまだ罪のように醜いですが、それは機能します。問題は、オブジェクトのメソッドCanBuildFromから取得するワイルドカードですが、幸いなことに、適切なタイプで独自のラッパーを作成できます。canBuildFromListCanBuildFrom

于 2012-07-26T23:19:48.643 に答える
5

コードでscalacが何をするか知りたい場合は、尋ねてください。;)

これは、scalac -Xprint:typer <file>または 2.10 の新しい Reflection API で可能です。

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> reify{List(1,2,3).map(_+1)}
res0: reflect.runtime.universe.Expr[List[Int]] = Expr[List[Int]](immutable.this.List.apply(1, 2, 3).map(((x$1) => x$1.$plus(1)))(immutable.this.List.canBuildFrom))

mapしたがって、これで呼び出すとCanBuildFrom、すべて正常に動作します。本当にそうですか?いいえ、そうではありません。問題は、Java コンパイラが が期待する引数を推測するのがばかげていることmapです。じゃあ何をすればいいの?唯一の方法は、必要な値を作成し、それらを死に追いやることだと思います。最後にいくつかSuppressWarnings-Annotationsを混ぜると、コードは正常に動作するはずです。;)

これは私が思いついたものです:

import scala.Function1;
import scala.collection.generic.CanBuildFrom;
import scala.collection.immutable.List;
import scala.collection.immutable.List$;
import scala.runtime.AbstractFunction1;

public class JTest {
  @SuppressWarnings({"unchecked", "rawtypes"})
  public static void main(final String... args) {
    final List<Integer> xxx = (List) List$.MODULE$.apply(Predef.wrapIntArray(new int[] {1,2,3}));
    System.out.println(xxx);

    System.out.println(Test.sum(1, 2));
    final Abc abc = new Abc();
    System.out.println(abc.hello("simon"));

    final List<Integer> xs = (List) Test.xs();
    final Function1<Integer, String> mapper = new AbstractFunction1<Integer, String>() {
      @Override
      public String apply(final Integer i) {
        return String.valueOf(i);
      }
    };
    final CanBuildFrom<List<Integer>, String, List<String>> cbf =
        (CanBuildFrom) List.<Integer>canBuildFrom();
    final List<String> ys = xs.<String, List<String>>map(mapper, cbf);
    System.out.println(ys);
  }
}

リスト:

object Test {
  def xs = List(1,2,3)
}

私は、Java から Scala コードを使用しないことが最善であると信じています。それは醜く見えます。少なくとも、このコードを見た人が網膜への酸攻撃について考えないように、いくつかのヘルパー クラスでラップしてください。

ところで、scalac がどのように値を作成するかを理解するために、Bytecode を見なければならないことがあります。Scala List is Java を作成する場合は、コードをjavap -c -s -l -verbose -private <classfile>次のように逆コンパイルする必要があります。

   0:   aload_0
   1:   invokespecial   #20; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   putstatic   #22; //Field MODULE$:LX$;
   8:   aload_0
   9:   getstatic   #27; //Field scala/collection/immutable/List$.MODULE$:Lscala/collection/immutable/List$;
   12:  getstatic   #32; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   15:  iconst_3
   16:  newarray int
   18:  dup
   19:  iconst_0
   20:  iconst_1
   21:  iastore
   22:  dup
   23:  iconst_1
   24:  iconst_2
   25:  iastore
   26:  dup
   27:  iconst_2
   28:  iconst_3
   29:  iastore
   30:  invokevirtual   #38; //Method scala/LowPriorityImplicits.wrapIntArray:([I)Lscala/collection/mutable/WrappedArray;
   33:  invokevirtual   #42; //Method scala/collection/immutable/List$.apply:(Lscala/collection/Seq;)Lscala/collection/immutable/List;
   36:  new #44; //class X$$anonfun$1

または、より読みやすい Java コードで:

@SuppressWarnings({"unchecked", "rawtypes"})
final List<Integer> xs = (List) List$.MODULE$.apply(Predef.wrapIntArray(new int[] {1,2,3}));
于 2012-07-26T23:08:55.987 に答える