在scala模板中循环浏览地图?
我有一张表示内容表的地图,它包含Chapter
键和List[Section]
值。 现在我试图在我的模板中循环这样:
<dl>
@table_of_contents.foreach((e) => {
<dt>
@e._1.title
</dt>
for(section <- e._2){
<dd>
@section.title
</dd>
}
})
</dl>
然而,我目前在<dl>
没有输出。
我在模板的顶部添加了一个println(table_of_contents)
语句,以确保该地图确实具有数据并将其打印出来:
{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[]}
也许我需要使用一种命令式的风格?
更新:
仍然在这方面...有这种变化编译,但没有输出。
<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;博士
迄今为止给出的答案(@wbarksdale,@PlexQ和@Daniel C. Sobral在评论中)足以说明这里描述的问题。
但他们错过了关于为什么使用foreach
的初始代码不起作用的真实解释。
它不能工作,因为foreach
返回Unit
。
玩概念
让我快速记下/回忆一下模板如何工作。
Play Framework 2默认提供的Scala模板系统确实是建立在FP概念上的,因此它使用了很多不可变的结构等等。
此外,这样的Scala模板(比如myTemplate.scala.html
)将被编译成一个常规的Scala object
,该object
具有一个名为apply
方法。 后一个函数使我们可以将该对象作为一个函数调用(在模板的第一行中声明的那些参数)。
这个object
也依赖于像使用输出格式化程序(Html)构建的BaseScalaTemplate
这样的构造。 这个格式化程序将能够获取东西(比如String
, Unit
, Seq[Int]
, Map[A,B]
,...)并将其呈现为HTML代码。
而使用格式化将于_display_
的方法BaseScalaTemplate
,它返回格式化输出的一个实例。 该显示方法将在对象的apply
方法体内的.scala.html
文件的编译代码中.scala.html
。
所以身体可以像这样结束:
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
)的实例!
这给了我们线索......
是的,等等等等......现在为什么?
在给出有关Play内幕的闪电之后,我们现在可以解决真正的问题:为什么地狱是在问题提供的意识形态Scala代码不工作...阅读,根本不输出任何内容。
这非常简单,当在Map
上使用foreach
时,你确实在遍历项目并将它们调整为Html。 但是这些计算不会被模板系统使用,因为它们被包含在foreach
的循环中。 当序列中的每个项目都需要副作用时,必须使用foreach
...并在完成时返回Unit
。
因为,模板系统将尝试_display_
结果foreach
给定的Map
它只会呈现/格式的Unit
,因此一个空String
!
总之,只需使用map
将返回一个新的序列,其中包含适应的项目, Html
实例。
嗯,什么对for
?
是啊,你说得对...基于说了些什么,为什么是建议使用的答案for
循环工作,因为没有产生一个值, for
相当于foreach
!? (引入yield
将以类似map
的行为结束)
答案在代码中...模板编译器会将yield
关键字添加到for
的主体 - 请在此查看。 :-D
等瞧,它的工作原理也是如此,因为在生成的东西for
,它已经完成后的遗体将被连接到一个返回序列。
我提出的解决方案看起来像这样。 基本上,它只是避免使用函数式编程,我暂时可以使用,但我仍然很希望看到使用scala函数式的工作解决方案。
<dl>
@for((key, value) <- table_of_contents) {
<dt>
@key.getTitle
</dt>
@displaySections(value)
}
</dl>
@displaySections(sections: List[Section]) = {
@for(a_section <- sections) {
<dd>@a_section.getTitle</li>
}
}
在斯卡拉玩Scala非常好用。 将其更改为返回元素的映射,它应该可以工作。
<dl>
@table_of_contents.map( case(k,v) => {
<dt>
@k.title
</dt>
@v.map { section =>
<dd>
@section.title
</dd>
}
})
</dl>
根据上面的建议,在这种情况下,它将它变成一个部分函数,它可以很好地完成我们想要的任务!
链接地址: http://www.djcxy.com/p/62631.html上一篇: Looping through a map in a scala template?
下一篇: Why does pattern matching in Scala not work with variables?