2012-03-30 12 views
13

私は、目次を表すマップを持っています。それはChapterのキーとList[Section]の値を含んでいます。今、私はこのように私のテンプレートでこのをループしようとしています:再生!フレームワーク2.0 - スケーラテンプレート内のマップをループしていますか?

<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)文を追加してデータを持っているし、それが印刷された:

{[email protected]=BeanList size[4] hasMoreRows[false] list[[email protected], [email protected], [email protected], [email protected]], [email protected]=BeanList size[0] hasMoreRows[false] list[]}

は、おそらく私が不可欠スタイルを使用する必要がありますか?

UPDATE

:まだこれに取り組んで

...コンパイルするには、この変化が、ノー出力を得ました。

<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> 
    } 
} 
+3

Playの経験はあまりありませんが、 'foreach'の戻り値の型が' Unit'なのではありますか?代わりに 'map'を使ってみましたか? – Gareth

+0

@Gareth私は正しいところで、 'foreach()'メソッドを呼び出す代わりに 'for()'構文を使うようにループを変更したと思います。 – wbarksdale

答えて

17

TL; DR

@wbarksdale@PlexQやコメントで@Daniel C. Sobralで)これまでに与えられた答えはここで説明する問題を対象とするのに十分な良いです。

しかし、foreachを使用して初期コードが機能しない理由についての実際の説明が欠落しています。

foreachUnitを返すため、機能しません。

プレイの概念

私はテンプレートがどのように機能するかについての簡単なメモ/リコールを挙げてみましょう。

Play Framework 2でデフォルトで提供されているScalaテンプレートシステムは、実際にはFPの概念に基づいているため、多くの不変構造などが使用されています。

さらに、このようなScalaテンプレート(myTemplate.scala.htmlと言う)は、applyというメソッドを持つ通常のScala objectにコンパイルされます。この後者の関数は、という名前のオブジェクトを(テンプレートの最初の行で宣言された)いくつかのパラメータを持つ関数として呼び出すことができます。

このobjectも、出力フォーマッタ(Html)で構築されたBaseScalaTemplateのような構成に依存しています。このフォーマッタは、(StringUnitSeq[Int]Map[A,B]、...のようなもの)をとり、HTMLコードにレンダリングすることができます。

メソッドがBaseScalaTemplateのときにフォーマットが行われ、形式の出力のインスタンスが返されます。この表示方法は、コード.scala.htmlのオブジェクトのapplyメソッドの本体にコンパイルされたコードで呼び出されます。

だから、体はそのように終わる可能性:

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コードが動作していない理由...読み込み、すべて。

それはMapforeachを使用しているとき、あなたはHTMLにそれらを適応させるアイテムやをループ確かしている、非常に簡単です。しかし、これらの計算は、foreachのループに囲まれているため、テンプレートシステムでは使用できません。シーケンスの各項目に副作用が必要な場合は、foreachを使用しなければなりません。完了したらUnitを返します。

テンプレートシステムは、それが単に/フォーマットUnitので、空Stringをレンダリングします与えられたMap_display_foreachの結果をしようとします、ので!

mapを使用すると、に適合したアイテムのHtmlインスタンスを保持する新しいシーケンスが返されます。

Hmmmとは何ですか?for?値を得ずに、forforeachと同等であるため、

うん、あなたは正しい...言われているものに基づいている、なぜ、forループの作業を使用することが提案されているの答えですか!?答えはコードである

yieldを導入することmap様行動に終了します)... forの体にyieldキーワードを付加しますテンプレートコンパイラは - hereこれをチェックしてください。ほら:-D

のEtそれが終了した後にforの体内で生成された詰め込むを返す配列に付着されるので、それは、あまりにも動作します。

+0

この回答のリンクは404ですが、私はPlayフレームワークでFor、Foreach、またはMapを使用するのにはまだ混乱しています。 pは必要な構造を吐き出すためにテンプレートをループします。 –

7

Scalaでの再生はScalaの機能を非常によく使用します。これを要素を返すマップに変更してください。うまくいくはずです。

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

上記の示唆によれば、このケースでは、それを部分的な機能に変えて、うまくいくようにします。

+0

ありがとう@PlexQ、私は ' '行の' @e._2.map {section => '。私は本当にScalaにあまりにもぶつかりませんでしたが、私はこれを投稿して以来それを学び始めており、それがどれほど表現力に驚くのです。本当にクールなもの! – wbarksdale

+0

私はそれを修正できるかどうか私に見てみましょう! – PlexQ

+0

okay - 更新してみてください – PlexQ

17

私が思いついた解決策は、このように見えました。基本的には、当分の間は私が大丈夫な関数型プログラミングを避けるだけですが、スカラ関数スタイルを使用した実用的なソリューションを見たいと思っています。

<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> 
    } 
} 
+4

'@table_of_contents.map {case(key、value)=>'。 –

+1

私はスカラができることに驚いています。 – PlexQ

関連する問題