Как использовать мой собственный шаблон Iterable в Play Framework

1

Проблема в двух словах

Я не могу перебирать слегка обернутую коллекцию в Play! Рамочный шаблон. Я сделал предположение, что просто реализация интерфейса Iterable позволит мне использовать для каждого цикла в шаблонах, но это кажется неправильным.

Как я могу заставить это работать?

Что я сделал

Я создал простой класс-оболочку вокруг java.util.Queue. Я сделал предположение, что реализация Iterable позволит мне использовать цикл for-each в Play! Рамочный шаблон.

public class DecisionQueue implements Iterable<Decision> {
    Queue<Decision> decisions;

    public DecisionQueue() {
        decisions = new LinkedList<Decision>();
    }

    // redacted methods for manipulating the queue

    @Override
    public Iterator<Decision> iterator() {
        return decisions.iterator();
    }
}

Я предоставил экземпляр оболочки для шаблона.

public static Result getFormOutput() {
    DecisionQueue decisionQueue = getDecisionQueue();

    return ok(views.html.questionnaire.output.render(decisionQueue));
}

Я попытался перебрать оболочку в свой шаблон.

@(decisionQueue: data.DecisionQueue)

<ul>
@for(decision <- decisionQueue) // Problem here
  // redacted
}
</ul>

Во время компиляции я получил следующую трассировку стека.

[error] C:\...\app\views\questionnaire\output.scala.html:12: type mismatch;
[error]  found   : decisionQueue.type (with underlying type models.data.DecisionQueue)
[error]  required: ?{def map(x$1: ? >: <error> => play.twirl.api.HtmlFormat.Appendable): ?}
[error]     (which expands to)  ?{def map(x$1: ? >: <error> => play.twirl.api.Html): ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error]  both method javaCollectionToScala in object TemplateMagic of type [T](x: Iterable[T])Iterable[T]
[error]  and method iterableAsScalaIterable in trait WrapAsScala of type [A](i: Iterable[A])Iterable[A]
[error]  are possible conversion functions from decisionQueue.type to ?{def map(x$1: ? >: <error> => play.twirl.api.HtmlFormat.Appendable): ?}
[error] @for(decision <- decisionQueue) {
[error]                             ^
[error] one error found
[error] (compile:compile) Compilation failed

Временное решение

Он работает, если я передаю базовую очередь непосредственно шаблону вместо использования обертки.

  • 1
    Похоже, что некая неявная магия поиска Scala не работает. В частности, похоже, что для добавления функциональности (возможно, функции map ) в Java Iterable существует два различных Iterable чтобы она работала как Scala Iterable . Я собираюсь добавить тег Scala, потому что там все идет не так.
  • 0
    Я полагал, что есть два пути, которыми это могло бы пойти: 1. Мой класс чего-то не хватает. В таком случае, что делает java.util.Queue , чего не делает мой класс? 2. Стандартным структурам данных Java было уделено особое внимание, и нет способа перебрать мой объект в Play! шаблон. Я хотел бы верить, что это # 1. Должен ли я понимать Scala, чтобы сделать эту работу?
Показать ещё 2 комментария
Теги:
playframework
twirl

2 ответа

1

Здесь вы смешиваете языки. Класс DecisionQueue написан на Java, а шаблоны Twirl - для Scala. Языки совместимы, но не прозрачно. Вы пытаетесь выполнить итерацию в Scala по коллекции Java (LinkedList). Scala не знает, как это сделать без какой-либо помощи, и ошибка говорит вам, что она обнаружила некоторую двусмысленность с неявными функциями, которые она пыталась использовать для преобразования коллекции Java. Возможно, вам захочется немного помочь, импортируя конвертеры и используя их, например:

@(decisionQueue: data.DecisionQueue)
import scala.collection.JavaConversions._
<ul>
@for(decision <- decisionQueue.iterator) // Problem here
  // redacted
}
</ul>
0

Просто была такая же проблема с Play 2.5.14 и исправлена, сделав преобразование явным, добавив .asScala. Думал, что я поделюсь своим решением, хотя вопрос старый, поскольку он появляется, когда googling play iterable implicit conversion ambiguous на первой позиции.

До

@(subscriptions: java.lang.Iterable[Subscription])
@if(subscriptions.nonEmpty) {
  ...
}

Дала мне эту ошибку:

[error] /some/path/accountDetails.scala.html:31: type mismatch;
[error]  found   : subscriptions.type (with underlying type Iterable[some.package.Subscription])
[error]  required: ?{def nonEmpty: ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error]  both method javaCollectionToScala in object TemplateMagic of type [T](x: Iterable[T])Iterable[T]
[error]  and method iterableAsScalaIterable in trait WrapAsScala of type [A](i: Iterable[A])Iterable[A]
[error]  are possible conversion functions from subscriptions.type to ?{def nonEmpty: ?}
[error]         @if(subscriptions.nonEmpty) {
[error]             ^

После

@(subscriptions: java.lang.Iterable[Subscription])
@if(subscriptions.asScala.nonEmpty) {
  ...
}

Работает из коробки для меня, дополнительный импорт не требуется.

Надеюсь, поможет.

Ещё вопросы

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