1

简而言之问题

我无法在Play 中迭代一个轻包装的集合!框架模板。我假设简单地实现Iterable接口将使我能够在模板中使用 for-each 循环,但这似乎是不正确的。

我怎样才能得到这个工作?

我做了什么

我围绕 java.util.Queue 创建了一个简单的包装类。我假设实现 Iterable 将允许我在Play 中使用 for-each 循环!框架模板。

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

解决方法

如果我将底层队列直接传递给模板而不是使用包装器,它会起作用。

4

2 回答 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>
于 2014-10-27T04:01:00.093 回答
0

Play 2.5.14 遇到了完全相同的问题,并通过添加.asScala. 即使问题很旧,我也想分享我的解决方案,因为它在谷歌搜索时出现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) {
  ...
}

对我来说开箱即用,不需要额外的进口。

希望能帮助到你。

于 2017-07-17T09:39:31.627 回答