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

查看:19
本文介绍了玩!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>

我目前在

中没有任何输出.

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@PlexQ@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)将被编译成一个具有 apply 的常规 Scala object方法调用.后一个函数使我们能够调用对象作为带有一些参数(在模板的第一行中声明的参数)的函数.

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 也依赖于像 BaseScalaTemplate 使用输出格式化程序 (Html) 构建.这个格式化程序将能够接受一些东西(比如 StringUnitSeq[Int]Map[A,B], ...) 并将其呈现为 HTML 代码.

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_ 调用不会改变任何东西,但它们的组合方式是 apply 本身将返回格式化代码的实例 (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 时,您确实循环在项目上并适应em> 将它们转换为 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_display_ foreach 的结果,它只会渲染/格式化 单位,因此是一个空的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 它将返回一个包含 适应 项的新序列,即 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)

答案在代码中...模板编译器会将 yield 关键字添加到 for 的正文中 -- 请查看 这里.:-D

The answer is in the code... The Template compiler will prepend the yield keyword to the for's body -- check this out here. :-D

等一下,它也可以工作,因为 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天全站免登陆