玩!Framework 2.0 - 通过scala模板中的地图循环?

wfb*_*ale 14 templates scala playframework playframework-2.0

我有一个表示目录的地图,它包含Chapter键和List[Section]值.现在我试图在我的模板中循环这样:

<dl>
@table_of_contents.foreach((e) => {
    <dt>
        @e._1.title
    </dt>
        for(section <- e._2){
        <dd>
            @section.title
        </dd>
        }
})
</dl>
Run Code Online (Sandbox Code Playgroud)

我目前没有输出<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>
  }
}
Run Code Online (Sandbox Code Playgroud)

and*_*lla 18

TL;博士

到目前为止给出的答案(@wbarksdale,@ PlexQ@Daniel C. Sobral在评论中)足以解决这里描述的问题.

但他们错过了关于为什么初始代码使用foreach不起作用的真实解释.

因为foreach退货而无法运作Unit.

玩概念

让我快速回顾一下模板的工作原理.

Play框架2中默认提供的Scala模板系统确实是基于FP概念构建的,因此它使用了大量不可变结构等等.

此外,这样的Scala模板(比如说myTemplate.scala.html)将被编译成一个常规的Scala object,它有一个apply名为的方法.后一个函数使我们能够将对象作为一个函数调用一些参数(在模板的第一行中声明的参数).

object也依赖于BaseScalaTemplate使用输出格式化程序(Html)构建的构造.这种格式将能够利用的东西(如String,Unit,Seq[Int],Map[A,B],...),并呈现到HTML代码.

使用_display_方法时将进行格式化,该方法BaseScalaTemplate返回格式化输出的实例.这个显示方法将在对象方法体中文件的编译代码中调用..scala.htmlapply

所以身体可能会这样结束:

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))))
          }
        )
      )
    )
  }
Run Code Online (Sandbox Code Playgroud)

看到?该_display_调用不变异什么,但它们在适用本身将返回格式化代码的实例,这样组成的(Html)!

这给了我们线索......

是啊等等......现在为什么?

在给出关于Play内部的闪电之后,我们现在可以解决真正的问题:为什么地狱是问题帖子中提供的意识形态Scala代码不起作用...读取,根本不输出任何内容.

这很简单,当你foreach在a上使用时Map,你确实在循环这些项目并使它们适应 Html.但是模板系统无法使用这些计算,因为它们被包含在foreach循环中.即foreach具有在需要的序列中的每一项副作用使用......并返回Unit时,它的完成.

因为,模板系统将尝试在给定_display_的结果foreachMap它将简单地渲染/格式Unit,因此是空的String!

总而言之,只需使用map它将返回一个包含适应项目的新序列,即Html实例.

嗯,怎么样for

是的,你是对的...根据已经说过的,为什么建议使用for循环工作的答案,因为没有产生一个值,a for相当于foreach!?(介绍yield将以类似map行为结束)

答案在代码中......模板编译器会将yield关键字添加到for主体 - 请在此处查看.:-D

Etvoilà,它也有效,因为生成的东西for会在完成之后附加到返回的序列中.


wfb*_*ale 17

我提出的解决方案看起来像这样.基本上它只是避免使用我目前正常使用的函数式编程,但我仍然希望看到一个使用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>
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 试试`@table_of_contents.map {case(key,value)=>`. (4认同)

Ple*_*exQ 8

Scala中的游戏非常好地使用了Scala的功能特性.将其更改为返回元素的地图,它应该可以工作.

<dl>
@table_of_contents.map( case(k,v) => {
    <dt>
        @k.title
    </dt>
    @v.map { section =>
        <dd>
            @section.title
        </dd>
    }
})
</dl>
Run Code Online (Sandbox Code Playgroud)

根据上面的建议,在这种情况下,它将它变成一个部分功能,可以很好地完成我们想要的功能!