玩! Framework 2.0-在Scala模板中循环遍历地图? [英] Play! Framework 2.0 - Looping through a map in a scala template?
问题描述
我有一个表示目录的映射,它包含Chapter
键和List[Section]
值.现在,我试图像这样在我的模板中循环遍历:
I have a map representing a table of contents, it contains Chapter
keys and List[Section]
values. Right now I am trying to loop through this in my template like this:
<dl>
@table_of_contents.foreach((e) => {
<dt>
@e._1.title
</dt>
for(section <- e._2){
<dd>
@section.title
</dd>
}
})
</dl>
但是我目前在<dl>
中没有任何输出.
I currently get no output in the <dl>
however.
我在模板顶部添加了println(table_of_contents)
语句,以确保地图确实具有数据并已打印:
I added a println(table_of_contents)
statement to the top of the template to ensure that the map did in fact have data and it printed:
{models.Chapter@1=BeanList size[4] hasMoreRows[false] list[models.Section@1, models.Section@2, models.Section@3, models.Section@4], models.Chapter@2=BeanList size[0] hasMoreRows[false] list[]}
也许我需要使用命令式风格?
perhaps I need to use an imperative style?
更新:
仍在进行此操作...使此变体可以编译但没有输出.
Still working on this... got this variation to compile but no output.
<dl>
@table_of_contents.foreach{case(a, b) => {
<dt>
@a.title
</dt>
@displaySections(b)
}}
</dl>
...
@displaySections(sections: List[Section]) = {
@for(a_section <- sections) {
<dd>@a_section.title</li>
}
}
推荐答案
tl; dr
到目前为止给出的答案(通过 @wbarksdale , @Daniel C. Sobral 在评论中)足以解决此处描述的问题.
The answers given so far (by @wbarksdale, @PlexQ and @Daniel C. Sobral in a comment) are good enough to target the problem described here.
但是他们没有真正解释为什么使用foreach
的初始代码不起作用.
But they're missing a real explanation about why the initial code, using foreach
, doesn't work.
它不能工作,因为foreach
返回Unit
.
It cannot work because foreach
returns Unit
.
播放概念
让我快速记录一下/回顾一下模板的工作原理.
Let me give a quick note/recall about how templates work.
Play Framework 2中默认提供的Scala模板系统确实是基于FP概念构建的,因此它使用了许多不可变的结构,等等.
The Scala templating system provided by default in Play Framework 2 is indeed built upon FP concepts and thus it uses a lot of immutable structures and so forth.
此外,这样的Scala模板(比如说myTemplate.scala.html
)将被编译成常规的Scala object
,该常规Scala具有称为apply
的方法.后一个功能使我们能够使用某些参数(在模板的第一行中声明的那些参数)作为对象的函数来调用.
Moreover, such Scala template (let's say myTemplate.scala.html
) will be compiled into a regular Scala object
which has an apply
method called. This latter function enables us to call the object as a function with some parameters (those declared in the first line of the template).
This object
is also relying on a construction like BaseScalaTemplate
which is built with an output formatter (Html). This formatter will be able to take stuff (like a String
, Unit
, Seq[Int]
, Map[A,B]
, ...) and render it into HTML code.
格式化将在使用BaseScalaTemplate
的_display_
方法时进行,该方法将返回格式化输出的实例.该显示方法将在对象的apply
方法主体中的.scala.html
文件的已编译代码中调用.
Formatting will take place while using the _display_
method of BaseScalaTemplate
, which returns an instance of the formatted output. This display method will be called in the compiled code of the .scala.html
file in the object's apply
method's body.
所以身体可能会这样结束:
So the body could end like that:
def apply/*1.2*/(testMap:scala.collection.immutable.Map[String, Int]):play.api.templates.Html =
_display_ {
Seq[Any](
_display_(
Seq[Any](
/*3.2*/testMap/*3.9*/.map/*3.13*/ { e =>
_display_(Seq[Any](_display_(Seq[Any](/*5.3*/e))))
}
)
)
)
}
看到了吗? _display_
调用没有任何变化,但是它们的构成方式是:应用自身将返回格式化代码(Html
)的实例!
See? The _display_
calls aren't mutating anything but they are composed in such a way that apply itself will return an instance of the formatted code (Html
)!
这给了我们线索...
That gives us the clue...
是的,等等...现在为什么?
给出关于Play内部的闪电之后,我们现在可以解决一个真正的问题:为什么问题帖中提供的意识形态Scala代码无法正常工作……阅读,根本不输出任何内容.
After those lightnings given about the Play internals, we can now tackle the real question: why the hell is the ideomatic Scala code provided in the question post isn't working... read, doesn't output anything at all.
这非常简单,当在Map
上使用foreach
时,您确实是在这些项目上进行循环并将它们适应到HTML.但是这些计算将不能被模板系统使用,因为它们被包含在foreach
的循环中.当序列中每个项目都需要副作用时,必须使用foreach
.完成后返回Unit
.
It's pretty simple, when using foreach
on a Map
, you're indeed looping over the items and adapting them to Html. But these computation won't be usable by the templating system because they are enclosed in the foreach
's loop. That is foreach
has to be used when side-effects are required for each item in the sequence... And return Unit
when it's done.
由于,模板系统将尝试在给定的Map
上对foreach
的结果进行_display_
,它将简单地渲染/格式化Unit
,因此为空的String
!
Since, the templating system will try to _display_
the result of foreach
on the given Map
it will simply render/format Unit
and thus an empty String
!
最后,只需使用map
即可返回一个包含 adapted 项的新序列,即Html
实例.
To conclude, just use map
which will return a new sequence holding the adapted items, the Html
instance.
嗯,for
又如何?
Hmmm and what about the for
?
是的,您是对的...根据所讲的内容,为什么建议使用for
循环的答案有效,因为在不产生值的情况下,for
等效于foreach
! (引入yield
将以类似map
的行为结束)
Yeah, you're right... Based on what has been said, why are the answers that proposed to used a for
loop working, since without yielding a value, a for
is equivalent to foreach
!? (Introducing yield
will end in a map
-like behavior)
答案就在代码中... Template编译器会将yield
关键字放在for
的正文之前-将此内容检出
The answer is in the code... The Template compiler will prepend the yield
keyword to the for
's body -- check this out here. :-D
Etvoilà也是如此,因为for
体内生成的填充物将在完成后附加到返回的序列上.
Et voilà, it works too, since the generated stuffs in the for
's body will be attached to a returned sequence after it has finished.
这篇关于玩! Framework 2.0-在Scala模板中循环遍历地图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!