玩! Framework 2.0-在Scala模板中循环遍历地图? [英] Play! Framework 2.0 - Looping through a map in a scala template?

查看:80
本文介绍了玩! Framework 2.0-在Scala模板中循环遍历地图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个表示目录的映射,它包含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).

object还依赖于

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆