Загадочное неявное преобразование во время Array map ()

1

У меня есть прецедент, когда мне дают Java-массив классов-оболочек, например, обертывание int, и я хочу преобразовать их в ValueSet из одних и тех же данных, но я столкнулся с загадочной проблемой с неявными преобразованиями. Вот пример Java и Scala, которые я пытаюсь сделать:

.../Java/demoapi/SomeWrapper.java

package demoapi;

public class SomeWrapper {
    public static final int JavaOne = 1;
    public static final int JavaTwo = 2;
    public int m_theInt;
};

.../Scala/demo.scala

package demotest

import demoapi._

object TestEnum extends Enumeration {
  val One, Two = Value
}

object SomeWrapperEx {
  implicit def fromJava(in: Array[SomeWrapper]): TestEnum.ValueSet = {
    in.map(x => fromInt(x.m_theInt))
  }
  def fromInt(in: Int): TestEnum.Value = {
    in match {
      case SomeWrapper.JavaOne => TestEnum.One
      case SomeWrapper.JavaTwo => TestEnum.Two
    }
  }
}

Карта не может скомпилироваться со следующей ошибкой:

Error:(11, 27) value m_theInt is not a member of demotest.TestEnum.Value
    in.map(x => fromInt(x.m_theInt))
                          ^

Мой вопрос: как уже был преобразован тип элемента массива в TestEnum.Value? Мне приходилось работать, бросая подобные импликации, но я чувствую, что это должно работать как-то...

EDIT: Я уверен, что мне нужно сделать больше, чтобы заставить его работать, например, возможно преобразовать Array [TestEnum.Value] в ValueSet, но я пока не дошел до этого.

Теги:
arrays
implicit
implicit-conversion

1 ответ

1
Лучший ответ

Вы ожидаете преобразовать свой массив в коллекцию (ArrayOps), чтобы вы могли работать с ней.

Но вы ожидаете создать ValueSet, и для этого машина нуждается в способе ее создания - CanBuildFrom.

Это подразумевалось здесь:

См. Документы для ValueSet.

Поскольку вы предоставляете способ преобразования своего массива в ValueSet, он с радостью применит его, чтобы использовать CanBuildFrom для него.

-Xprint:typer показывает вам направление, которое он принимает:

implicit def fromJava(in: Array[demoapi.SomeWrapper]): demoapi.TestEnum.ValueSet = SomeWrapperEx.this.fromJava(in).map[Nothing, demoapi.TestEnum.ValueSet](((x: demoapi.TestEnum.Value) => SomeWrapperEx.this.fromInt(x.<m_theInt: error>)))(demoapi.this.TestEnum.ValueSet.canBuildFrom);

У меня также возникают проблемы с работой с ValueSet как обычной коллекцией, так что теперь я этого не делаю.

Например, всегда начинайте с ValueSet:

$ scala
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala> object Days extends Enumeration { val M,T,W,Th,F,Sa,S = Value }
defined object Days

scala> val ds = (2 to 5).toArray
ds: Array[Int] = Array(2, 3, 4, 5)

scala> Days.values filter (ds contains _.id)
res0: Days.ValueSet = Days.ValueSet(W, Th, F, Sa)

или построить вручную:

scala> Days.ValueSet.empty
res1: Days.ValueSet = Days.ValueSet()

scala> res1 + Days.T
res2: Days.ValueSet = Days.ValueSet(T)

все это CanBuildFrom делает так или иначе:

scala> implicit val xxx = new collection.generic.CanBuildFrom[Array[Int], Days.Value, Days.ValueSet] {
     | def apply() = Days.ValueSet.newBuilder
     | def apply(from: Array[Int]) = apply()
     | }
xxx: scala.collection.generic.CanBuildFrom[Array[Int],Days.Value,Days.ValueSet] = $anon$1@6b474074

scala> (2 to 5) map (_ => Days.T)
res4: scala.collection.immutable.IndexedSeq[Days.Value] = Vector(T, T, T, T)

scala> (2 to 5) map (Days(_))
res5: scala.collection.immutable.IndexedSeq[Days.Value] = Vector(W, Th, F, Sa)
  • 0
    Итак, использует ли я функцию, которую я реализую, чтобы неявно преобразовать аргумент массива в ту же самую функцию? Это очень сложно. Итак, продолжение: учитывая, что у меня есть массив Java-объектов Java с элементом int, каков канонический способ преобразовать это в набор значений? Должен ли я предоставить только метод для преобразования одного объекта в одно значение, а затем позволить неявному материалу CanBuildFrom волшебным образом преобразовать контейнер X в ValueSet of Value? Будет ли это работать?
  • 0
    @experquisite Если вы хотите закончить набором значений, начните с набора значений. В противном случае постройте его вручную.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню